@meshconnect/uwc-injected-connector 0.2.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.
Files changed (83) hide show
  1. package/dist/eip6963-discovery.d.ts +47 -0
  2. package/dist/eip6963-discovery.d.ts.map +1 -0
  3. package/dist/eip6963-discovery.js +58 -0
  4. package/dist/eip6963-discovery.js.map +1 -0
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +4 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/injected-connector.d.ts +40 -0
  10. package/dist/injected-connector.d.ts.map +1 -0
  11. package/dist/injected-connector.js +183 -0
  12. package/dist/injected-connector.js.map +1 -0
  13. package/dist/injected-connector.old.d.ts +44 -0
  14. package/dist/injected-connector.old.d.ts.map +1 -0
  15. package/dist/injected-connector.old.js +491 -0
  16. package/dist/injected-connector.old.js.map +1 -0
  17. package/dist/providers/evm-provider.d.ts +18 -0
  18. package/dist/providers/evm-provider.d.ts.map +1 -0
  19. package/dist/providers/evm-provider.js +86 -0
  20. package/dist/providers/evm-provider.js.map +1 -0
  21. package/dist/providers/solana-provider.d.ts +22 -0
  22. package/dist/providers/solana-provider.d.ts.map +1 -0
  23. package/dist/providers/solana-provider.js +137 -0
  24. package/dist/providers/solana-provider.js.map +1 -0
  25. package/dist/services/connection-manager.d.ts +56 -0
  26. package/dist/services/connection-manager.d.ts.map +1 -0
  27. package/dist/services/connection-manager.js +303 -0
  28. package/dist/services/connection-manager.js.map +1 -0
  29. package/dist/services/ethereum-transaction-service.d.ts +28 -0
  30. package/dist/services/ethereum-transaction-service.d.ts.map +1 -0
  31. package/dist/services/ethereum-transaction-service.js +143 -0
  32. package/dist/services/ethereum-transaction-service.js.map +1 -0
  33. package/dist/services/ethereum-wallet-service.d.ts +55 -0
  34. package/dist/services/ethereum-wallet-service.d.ts.map +1 -0
  35. package/dist/services/ethereum-wallet-service.js +133 -0
  36. package/dist/services/ethereum-wallet-service.js.map +1 -0
  37. package/dist/services/index.d.ts +8 -0
  38. package/dist/services/index.d.ts.map +1 -0
  39. package/dist/services/index.js +8 -0
  40. package/dist/services/index.js.map +1 -0
  41. package/dist/services/signature-service.d.ts +16 -0
  42. package/dist/services/signature-service.d.ts.map +1 -0
  43. package/dist/services/signature-service.js +63 -0
  44. package/dist/services/signature-service.js.map +1 -0
  45. package/dist/services/solana-transaction-service.d.ts +14 -0
  46. package/dist/services/solana-transaction-service.d.ts.map +1 -0
  47. package/dist/services/solana-transaction-service.js +48 -0
  48. package/dist/services/solana-transaction-service.js.map +1 -0
  49. package/dist/services/solana-wallet-service.d.ts +55 -0
  50. package/dist/services/solana-wallet-service.d.ts.map +1 -0
  51. package/dist/services/solana-wallet-service.js +129 -0
  52. package/dist/services/solana-wallet-service.js.map +1 -0
  53. package/dist/services/storage-service.d.ts +19 -0
  54. package/dist/services/storage-service.d.ts.map +1 -0
  55. package/dist/services/storage-service.js +41 -0
  56. package/dist/services/storage-service.js.map +1 -0
  57. package/dist/services/transaction-service.d.ts +28 -0
  58. package/dist/services/transaction-service.d.ts.map +1 -0
  59. package/dist/services/transaction-service.js +67 -0
  60. package/dist/services/transaction-service.js.map +1 -0
  61. package/dist/utils/error-utils.d.ts +6 -0
  62. package/dist/utils/error-utils.d.ts.map +1 -0
  63. package/dist/utils/error-utils.js +55 -0
  64. package/dist/utils/error-utils.js.map +1 -0
  65. package/dist/wallet-standard-discovery.d.ts +24 -0
  66. package/dist/wallet-standard-discovery.d.ts.map +1 -0
  67. package/dist/wallet-standard-discovery.js +74 -0
  68. package/dist/wallet-standard-discovery.js.map +1 -0
  69. package/package.json +42 -0
  70. package/src/eip6963-discovery.ts +103 -0
  71. package/src/index.ts +7 -0
  72. package/src/injected-connector.ts +265 -0
  73. package/src/services/connection-manager.ts +437 -0
  74. package/src/services/ethereum-transaction-service.ts +196 -0
  75. package/src/services/ethereum-wallet-service.ts +161 -0
  76. package/src/services/index.ts +7 -0
  77. package/src/services/signature-service.ts +84 -0
  78. package/src/services/solana-transaction-service.ts +68 -0
  79. package/src/services/solana-wallet-service.ts +161 -0
  80. package/src/services/storage-service.ts +44 -0
  81. package/src/services/transaction-service.ts +106 -0
  82. package/src/utils/error-utils.ts +62 -0
  83. package/src/wallet-standard-discovery.ts +102 -0
@@ -0,0 +1,196 @@
1
+ import { ethers } from 'ethers'
2
+ import type { EthereumProvider } from '../eip6963-discovery'
3
+ import type {
4
+ EVMGasConfig,
5
+ EVMNativeTransferRequest,
6
+ EVMContractCallRequest,
7
+ EVMBatchTransactionRequest,
8
+ EVMCapabilities,
9
+ BatchTransactionResult
10
+ } from '@meshconnect/uwc-types'
11
+ import { parseError } from '../utils/error-utils'
12
+
13
+ /**
14
+ * Service for handling Ethereum/EVM transaction operations
15
+ */
16
+ export class EthereumTransactionService {
17
+ /**
18
+ * Send native token transfer (ETH, BNB, MATIC, etc.)
19
+ */
20
+ async sendNativeTransfer(
21
+ provider: EthereumProvider,
22
+ request: EVMNativeTransferRequest
23
+ ): Promise<string> {
24
+ try {
25
+ // Get current chain ID
26
+ const chainIdHex = await provider.request({
27
+ method: 'eth_chainId'
28
+ })
29
+ const chainId = parseInt(chainIdHex, 16)
30
+
31
+ // Create ethers provider and signer
32
+ const ethersProvider = new ethers.BrowserProvider(provider)
33
+ const signer = await ethersProvider.getSigner(request.from)
34
+
35
+ // Verify network hasn't changed
36
+ const network = await ethersProvider.getNetwork()
37
+ if (Number(network.chainId) !== chainId) {
38
+ throw new Error('Network changed during transaction setup')
39
+ }
40
+
41
+ // Build transaction
42
+ const tx = await signer.sendTransaction({
43
+ to: request.to,
44
+ value: request.amount,
45
+ ...this.formatGasConfig(request.gasConfig)
46
+ })
47
+
48
+ // Wait for confirmation
49
+ const receipt = await tx.wait()
50
+ return receipt ? receipt.hash : ''
51
+ } catch (error) {
52
+ parseError(error)
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Send smart contract transaction (including ERC-20 transfers)
58
+ */
59
+ async sendContractCall(
60
+ provider: EthereumProvider,
61
+ request: EVMContractCallRequest
62
+ ): Promise<string> {
63
+ try {
64
+ // Get current chain ID
65
+ const chainIdHex = await provider.request({
66
+ method: 'eth_chainId'
67
+ })
68
+ const chainId = parseInt(chainIdHex, 16)
69
+
70
+ // Create ethers provider and signer
71
+ const ethersProvider = new ethers.BrowserProvider(provider)
72
+ const signer = await ethersProvider.getSigner(request.from)
73
+
74
+ // Verify network hasn't changed
75
+ const network = await ethersProvider.getNetwork()
76
+ if (Number(network.chainId) !== chainId) {
77
+ throw new Error('Network changed during transaction setup')
78
+ }
79
+
80
+ // Create contract instance
81
+ const contract = new ethers.Contract(
82
+ request.contractAddress,
83
+ request.abi,
84
+ signer
85
+ )
86
+
87
+ // Build transaction options
88
+ const txOptions: ethers.Overrides = {
89
+ ...this.formatGasConfig(request.gasConfig)
90
+ }
91
+
92
+ // Add value for payable functions
93
+ if (request.value) {
94
+ txOptions.value = request.value
95
+ }
96
+
97
+ // Call the contract function
98
+ const contractFunction = contract[request.functionName]
99
+ if (!contractFunction) {
100
+ throw new Error(
101
+ `Function ${request.functionName} not found in contract`
102
+ )
103
+ }
104
+ const tx = await contractFunction(...request.args, txOptions)
105
+
106
+ // Wait for confirmation
107
+ const receipt = await tx.wait()
108
+ return receipt ? receipt.hash : ''
109
+ } catch (error) {
110
+ parseError(error)
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Send batch of transactions (EIP-5792)
116
+ */
117
+ async sendBatch(
118
+ provider: EthereumProvider,
119
+ request: EVMBatchTransactionRequest
120
+ ): Promise<string> {
121
+ try {
122
+ const ethersProvider = new ethers.BrowserProvider(provider)
123
+
124
+ // Send batch transaction
125
+ const response: { id: string } = await ethersProvider.send(
126
+ 'wallet_sendCalls',
127
+ [request]
128
+ )
129
+
130
+ // Poll for completion
131
+ let result: BatchTransactionResult
132
+ do {
133
+ result = await ethersProvider.send('wallet_getCallsStatus', [
134
+ response.id
135
+ ])
136
+
137
+ // Wait 1 second if still pending
138
+ if (result.status === 100) {
139
+ await new Promise(resolve => setTimeout(resolve, 1000))
140
+ }
141
+ } while (result.status === 100)
142
+
143
+ // Check if successful
144
+ if (result.status !== 200) {
145
+ throw new Error('Batch transaction failed')
146
+ }
147
+
148
+ // Return first transaction hash
149
+ const firstReceipt = result.receipts.find(r => r)
150
+ if (!firstReceipt) {
151
+ throw new Error('No transaction receipt found')
152
+ }
153
+
154
+ return firstReceipt.transactionHash
155
+ } catch (error) {
156
+ parseError(error)
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Get wallet capabilities (EIP-5792 support)
162
+ */
163
+ async getCapabilities(
164
+ provider: EthereumProvider,
165
+ from: string,
166
+ chainId: string
167
+ ): Promise<EVMCapabilities> {
168
+ const ethersProvider = new ethers.BrowserProvider(provider)
169
+ const capabilities = await ethersProvider.send('wallet_getCapabilities', [
170
+ from,
171
+ [chainId]
172
+ ])
173
+ return capabilities[chainId] || {}
174
+ }
175
+
176
+ /**
177
+ * Helper to format gas configuration for ethers
178
+ */
179
+ private formatGasConfig(gasConfig?: EVMGasConfig): ethers.Overrides {
180
+ const txOptions: ethers.Overrides = {}
181
+
182
+ if (gasConfig?.gasLimit) {
183
+ txOptions.gasLimit = BigInt(Math.floor(gasConfig.gasLimit))
184
+ }
185
+ if (gasConfig?.maxFeePerGas) {
186
+ txOptions.maxFeePerGas = BigInt(Math.floor(gasConfig.maxFeePerGas))
187
+ }
188
+ if (gasConfig?.maxPriorityFeePerGas) {
189
+ txOptions.maxPriorityFeePerGas = BigInt(
190
+ Math.floor(gasConfig.maxPriorityFeePerGas)
191
+ )
192
+ }
193
+
194
+ return txOptions
195
+ }
196
+ }
@@ -0,0 +1,161 @@
1
+ import type { NetworkId, AvailableAddress } from '@meshconnect/uwc-types'
2
+ import type {
3
+ EthereumProvider,
4
+ DetectedWallet as EIP6963DetectedWallet
5
+ } from '../eip6963-discovery'
6
+ import { getAvailableWallets as getEIP6963Wallets } from '../eip6963-discovery'
7
+
8
+ /**
9
+ * Service for managing Ethereum wallet connections
10
+ */
11
+ export class EthereumWalletService {
12
+ private detectedWallets: EIP6963DetectedWallet[] = []
13
+ private connectedProvider: EthereumProvider | null = null
14
+ private account: string | null = null
15
+
16
+ /**
17
+ * Initialize wallet discovery
18
+ */
19
+ async initializeDiscovery(): Promise<void> {
20
+ this.detectedWallets = await getEIP6963Wallets()
21
+ }
22
+
23
+ /**
24
+ * Get detected wallets
25
+ */
26
+ getDetectedWallets(): EIP6963DetectedWallet[] {
27
+ return this.detectedWallets
28
+ }
29
+
30
+ /**
31
+ * Find wallet by UUID
32
+ */
33
+ findWalletByUuid(uuid: string): EIP6963DetectedWallet | undefined {
34
+ return this.detectedWallets.find(w => w.uuid === uuid)
35
+ }
36
+
37
+ /**
38
+ * Check if a wallet is already connected without requesting access
39
+ */
40
+ async checkExistingConnection(
41
+ provider: EthereumProvider
42
+ ): Promise<string[] | null> {
43
+ try {
44
+ // Try eth_accounts which doesn't prompt user
45
+ const accounts = await provider.request({
46
+ method: 'eth_accounts'
47
+ })
48
+ return accounts && accounts.length > 0 ? accounts : null
49
+ } catch {
50
+ return null
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Connect to wallet
56
+ */
57
+ async connect(provider: EthereumProvider): Promise<string> {
58
+ const accounts = await provider.request({
59
+ method: 'eth_requestAccounts'
60
+ })
61
+
62
+ if (!accounts || accounts.length === 0) {
63
+ throw new Error('No accounts returned from wallet')
64
+ }
65
+
66
+ const address = accounts[0]
67
+ this.connectedProvider = provider
68
+ this.account = address
69
+
70
+ // Request chain ID to ensure we're connected
71
+ await provider.request({
72
+ method: 'eth_chainId'
73
+ })
74
+
75
+ return address
76
+ }
77
+
78
+ /**
79
+ * Switch network
80
+ */
81
+ async switchNetwork(networkId: string): Promise<void> {
82
+ if (!this.connectedProvider) {
83
+ throw new Error('No Ethereum wallet connected')
84
+ }
85
+
86
+ // Extract chain ID from network.id (format: "eip155:1")
87
+ const chainIdParts = networkId.split(':')
88
+ if (chainIdParts.length !== 2 || !chainIdParts[1]) {
89
+ throw new Error(`Invalid network ID format: ${networkId}`)
90
+ }
91
+ const chainId = chainIdParts[1]
92
+ const chainIdHex = `0x${parseInt(chainId, 10).toString(16)}`
93
+
94
+ // Try to switch to the requested chain
95
+ try {
96
+ await this.connectedProvider.request({
97
+ method: 'wallet_switchEthereumChain',
98
+ params: [{ chainId: chainIdHex }]
99
+ })
100
+ } catch (switchError: unknown) {
101
+ // This error code indicates that the chain has not been added to the wallet
102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
+ if ((switchError as any).code === 4902) {
104
+ throw new Error(`Chain ${networkId} is not added to the wallet`)
105
+ }
106
+ throw switchError
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Build available addresses for all supported networks
112
+ */
113
+ buildAvailableAddresses(
114
+ supportedNetworkIds: string[],
115
+ address: string
116
+ ): AvailableAddress[] {
117
+ const addresses: AvailableAddress[] = []
118
+ supportedNetworkIds.forEach(networkId => {
119
+ if (networkId.startsWith('eip155:')) {
120
+ addresses.push({
121
+ address,
122
+ networkId: networkId as NetworkId
123
+ })
124
+ }
125
+ })
126
+ return addresses
127
+ }
128
+
129
+ /**
130
+ * Set connection state
131
+ */
132
+ setConnectionState(
133
+ provider: EthereumProvider | null,
134
+ account: string | null
135
+ ): void {
136
+ this.connectedProvider = provider
137
+ this.account = account
138
+ }
139
+
140
+ /**
141
+ * Get current account
142
+ */
143
+ getAccount(): string | null {
144
+ return this.account
145
+ }
146
+
147
+ /**
148
+ * Get connected provider
149
+ */
150
+ getConnectedProvider(): EthereumProvider | null {
151
+ return this.connectedProvider
152
+ }
153
+
154
+ /**
155
+ * Disconnect (clear state only)
156
+ */
157
+ disconnect(): void {
158
+ this.connectedProvider = null
159
+ this.account = null
160
+ }
161
+ }
@@ -0,0 +1,7 @@
1
+ export { StorageService } from './storage-service'
2
+ export { EthereumWalletService } from './ethereum-wallet-service'
3
+ export { SolanaWalletService } from './solana-wallet-service'
4
+ export { ConnectionManager } from './connection-manager'
5
+ export { SignatureService } from './signature-service'
6
+ export { TransactionService } from './transaction-service'
7
+ export { EthereumTransactionService } from './ethereum-transaction-service'
@@ -0,0 +1,84 @@
1
+ import type { EthereumProvider } from '../eip6963-discovery'
2
+ import type { WalletAdapter } from '@solana/wallet-adapter-base'
3
+ import bs58 from 'bs58'
4
+ import { parseError } from '../utils/error-utils'
5
+
6
+ /**
7
+ * Service for handling message signing operations for injected wallets
8
+ */
9
+ export class SignatureService {
10
+ /**
11
+ * Sign a message with an Ethereum wallet
12
+ */
13
+ async signEthereumMessage(
14
+ message: string,
15
+ address: string,
16
+ provider: EthereumProvider
17
+ ): Promise<string> {
18
+ if (!provider) {
19
+ throw new Error('Provider is required for Ethereum message signing')
20
+ }
21
+
22
+ if (!message) {
23
+ throw new Error('Message is required for signing')
24
+ }
25
+
26
+ if (!address) {
27
+ throw new Error('Address is required for signing')
28
+ }
29
+
30
+ try {
31
+ // Use personal_sign for Ethereum
32
+ const signature = await provider.request({
33
+ method: 'personal_sign',
34
+ params: [message, address]
35
+ })
36
+
37
+ return signature
38
+ } catch (error) {
39
+ parseError(error)
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Sign a message with a Solana wallet
45
+ */
46
+ async signSolanaMessage(
47
+ message: string,
48
+ adapter: WalletAdapter
49
+ ): Promise<string> {
50
+ if (!adapter) {
51
+ throw new Error('Adapter is required for Solana message signing')
52
+ }
53
+
54
+ if (!message) {
55
+ throw new Error('Message is required for signing')
56
+ }
57
+
58
+ // Check if adapter supports signMessage
59
+ const signingAdapter = adapter as WalletAdapter & {
60
+ signMessage?: (message: Uint8Array) => Promise<Uint8Array>
61
+ }
62
+
63
+ if (!signingAdapter.signMessage) {
64
+ throw new Error('Solana adapter does not support message signing')
65
+ }
66
+
67
+ try {
68
+ // Convert message to Uint8Array for Solana
69
+ const encoder = new TextEncoder()
70
+ const messageBytes = encoder.encode(message)
71
+
72
+ // Sign the message
73
+ const signedMessage = await signingAdapter.signMessage(messageBytes)
74
+
75
+ // Encode signature using base58 for Solana (standard encoding for Solana)
76
+ // The signature is returned as a Uint8Array, encode it to base58 string
77
+ const signatureBase58 = bs58.encode(signedMessage)
78
+
79
+ return signatureBase58
80
+ } catch (error) {
81
+ parseError(error)
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,68 @@
1
+ import {
2
+ PublicKey,
3
+ SystemProgram,
4
+ Transaction,
5
+ Connection
6
+ } from '@solana/web3.js'
7
+ import type { WalletAdapter } from '@solana/wallet-adapter-base'
8
+ import type { SolanaNativeTransferRequest, NetworkRpcMap, NetworkId } from '@meshconnect/uwc-types'
9
+ import { parseError } from '../utils/error-utils'
10
+
11
+ /**
12
+ * Service for handling Solana transaction operations
13
+ */
14
+ export class SolanaTransactionService {
15
+ private networkRpcMap: NetworkRpcMap
16
+
17
+ constructor(networkRpcMap: NetworkRpcMap = {}) {
18
+ this.networkRpcMap = networkRpcMap
19
+ }
20
+
21
+ /**
22
+ * Send native SOL transfer
23
+ */
24
+ async sendNativeTransfer(
25
+ adapter: WalletAdapter,
26
+ request: SolanaNativeTransferRequest,
27
+ networkId?: NetworkId
28
+ ): Promise<string> {
29
+ try {
30
+ if (!adapter.publicKey) {
31
+ throw new Error('Wallet not connected')
32
+ }
33
+
34
+ // Verify the from address matches connected wallet
35
+ if (adapter.publicKey.toBase58() !== request.from) {
36
+ throw new Error('From address does not match connected wallet')
37
+ }
38
+
39
+ // Blockhash is required
40
+ if (!request.blockhash) {
41
+ throw new Error('Blockhash is required for Solana transactions')
42
+ }
43
+
44
+ // Create transaction
45
+ const transaction = new Transaction().add(
46
+ SystemProgram.transfer({
47
+ fromPubkey: new PublicKey(request.from),
48
+ toPubkey: new PublicKey(request.to),
49
+ lamports: Number(request.amount)
50
+ })
51
+ )
52
+
53
+ transaction.recentBlockhash = request.blockhash
54
+ transaction.feePayer = adapter.publicKey
55
+
56
+ // Get RPC URL from the network RPC map or fall back to public endpoint
57
+ const rpcUrl = networkId && this.networkRpcMap[networkId]
58
+ ? this.networkRpcMap[networkId]
59
+ : 'https://api.mainnet-beta.solana.com'
60
+ const connection = new Connection(rpcUrl)
61
+
62
+ const signature = await adapter.sendTransaction(transaction, connection)
63
+ return signature
64
+ } catch (error) {
65
+ parseError(error)
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,161 @@
1
+ import type { NetworkId, AvailableAddress } from '@meshconnect/uwc-types'
2
+ import type { WalletAdapter } from '@solana/wallet-adapter-base'
3
+ import {
4
+ getSolanaWallets,
5
+ type WalletStandardInfo
6
+ } from '../wallet-standard-discovery'
7
+ import { StorageService } from './storage-service'
8
+
9
+ /**
10
+ * Service for managing Solana wallet connections
11
+ */
12
+ export class SolanaWalletService {
13
+ private detectedWallets: WalletStandardInfo[] = []
14
+ private connectedAdapter: WalletAdapter | null = null
15
+ private account: string | null = null
16
+ private storageService: StorageService
17
+
18
+ constructor(storageService: StorageService) {
19
+ this.storageService = storageService
20
+ }
21
+
22
+ /**
23
+ * Initialize wallet discovery
24
+ */
25
+ initializeDiscovery(): void {
26
+ this.detectedWallets = getSolanaWallets()
27
+ }
28
+
29
+ /**
30
+ * Get detected wallets
31
+ */
32
+ getDetectedWallets(): WalletStandardInfo[] {
33
+ return this.detectedWallets
34
+ }
35
+
36
+ /**
37
+ * Find wallet by UUID
38
+ */
39
+ findWalletByUuid(uuid: string): WalletStandardInfo | undefined {
40
+ return this.detectedWallets.find(w => w.uuid === uuid)
41
+ }
42
+
43
+ /**
44
+ * Check if a Solana wallet is already connected
45
+ */
46
+ async checkExistingConnection(
47
+ adapter: WalletAdapter,
48
+ walletUuid: string
49
+ ): Promise<string | null> {
50
+ try {
51
+ // Check if adapter has a publicKey (means it's connected)
52
+ if (adapter.publicKey) {
53
+ return adapter.publicKey.toBase58()
54
+ }
55
+
56
+ // If this wallet was previously connected, try to reconnect
57
+ // This should work without prompting for wallets that support it
58
+ if (this.storageService.wasSolanaWalletPreviouslyConnected(walletUuid)) {
59
+ if (
60
+ 'connecting' in adapter &&
61
+ !adapter.connecting &&
62
+ 'connect' in adapter
63
+ ) {
64
+ try {
65
+ // Type assertion needed because TypeScript can't narrow the type properly
66
+ await adapter.connect()
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ const publicKey = (adapter as any).publicKey
69
+ if (publicKey && 'toBase58' in publicKey) {
70
+ return publicKey.toBase58()
71
+ }
72
+ } catch {
73
+ // Silent fail - wallet requires user interaction or doesn't support silent reconnect
74
+ }
75
+ }
76
+ }
77
+ return null
78
+ } catch {
79
+ return null
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Connect to wallet
85
+ */
86
+ async connect(adapter: WalletAdapter, walletUuid: string): Promise<string> {
87
+ // Connect to the Solana wallet
88
+ await adapter.connect()
89
+
90
+ if (!adapter.publicKey) {
91
+ throw new Error('No public key returned from wallet')
92
+ }
93
+
94
+ const address = adapter.publicKey.toBase58()
95
+ this.connectedAdapter = adapter
96
+ this.account = address
97
+
98
+ // Store this wallet as connected
99
+ this.storageService.storeSolanaWalletUUID(walletUuid)
100
+
101
+ return address
102
+ }
103
+
104
+ /**
105
+ * Build available addresses for all supported networks
106
+ */
107
+ buildAvailableAddresses(
108
+ supportedNetworkIds: string[],
109
+ address: string
110
+ ): AvailableAddress[] {
111
+ const addresses: AvailableAddress[] = []
112
+ supportedNetworkIds.forEach(networkId => {
113
+ if (networkId.startsWith('solana:')) {
114
+ addresses.push({
115
+ address,
116
+ networkId: networkId as NetworkId
117
+ })
118
+ }
119
+ })
120
+ return addresses
121
+ }
122
+
123
+ /**
124
+ * Set connection state
125
+ */
126
+ setConnectionState(
127
+ adapter: WalletAdapter | null,
128
+ account: string | null,
129
+ walletUuid?: string
130
+ ): void {
131
+ this.connectedAdapter = adapter
132
+ this.account = account
133
+
134
+ // Store wallet UUID if provided and connected
135
+ if (adapter && account && walletUuid) {
136
+ this.storageService.storeSolanaWalletUUID(walletUuid)
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Get current account
142
+ */
143
+ getAccount(): string | null {
144
+ return this.account
145
+ }
146
+
147
+ /**
148
+ * Get connected adapter
149
+ */
150
+ getConnectedAdapter(): WalletAdapter | null {
151
+ return this.connectedAdapter
152
+ }
153
+
154
+ /**
155
+ * Disconnect (clear state only, don't actually disconnect from wallet)
156
+ */
157
+ disconnect(): void {
158
+ this.connectedAdapter = null
159
+ this.account = null
160
+ }
161
+ }