@meshconnect/uwc-injected-connector 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/injected-connector.d.ts +5 -1
  2. package/dist/injected-connector.d.ts.map +1 -1
  3. package/dist/injected-connector.js +8 -2
  4. package/dist/injected-connector.js.map +1 -1
  5. package/dist/services/connection-manager.d.ts +2 -2
  6. package/dist/services/connection-manager.d.ts.map +1 -1
  7. package/dist/services/connection-manager.js +2 -2
  8. package/dist/services/connection-manager.js.map +1 -1
  9. package/dist/services/ethereum/ethereum-transaction-builder.d.ts +14 -0
  10. package/dist/services/ethereum/ethereum-transaction-builder.d.ts.map +1 -0
  11. package/dist/services/ethereum/ethereum-transaction-builder.js +60 -0
  12. package/dist/services/ethereum/ethereum-transaction-builder.js.map +1 -0
  13. package/dist/services/ethereum/ethereum-transaction-service.d.ts +26 -0
  14. package/dist/services/ethereum/ethereum-transaction-service.d.ts.map +1 -0
  15. package/dist/services/ethereum/ethereum-transaction-service.js +145 -0
  16. package/dist/services/ethereum/ethereum-transaction-service.js.map +1 -0
  17. package/dist/services/ethereum/ethereum-wallet-service.d.ts +59 -0
  18. package/dist/services/ethereum/ethereum-wallet-service.d.ts.map +1 -0
  19. package/dist/services/ethereum/ethereum-wallet-service.js +173 -0
  20. package/dist/services/ethereum/ethereum-wallet-service.js.map +1 -0
  21. package/dist/services/ethereum-transaction-service.d.ts +3 -0
  22. package/dist/services/ethereum-transaction-service.d.ts.map +1 -1
  23. package/dist/services/ethereum-transaction-service.js +83 -34
  24. package/dist/services/ethereum-transaction-service.js.map +1 -1
  25. package/dist/services/index.d.ts +3 -3
  26. package/dist/services/index.d.ts.map +1 -1
  27. package/dist/services/index.js +3 -3
  28. package/dist/services/index.js.map +1 -1
  29. package/dist/services/solana/solana-transaction-builder.d.ts +20 -0
  30. package/dist/services/solana/solana-transaction-builder.d.ts.map +1 -0
  31. package/dist/services/solana/solana-transaction-builder.js +112 -0
  32. package/dist/services/solana/solana-transaction-builder.js.map +1 -0
  33. package/dist/services/solana/solana-transaction-service.d.ts +27 -0
  34. package/dist/services/solana/solana-transaction-service.d.ts.map +1 -0
  35. package/dist/services/solana/solana-transaction-service.js +136 -0
  36. package/dist/services/solana/solana-transaction-service.js.map +1 -0
  37. package/dist/services/solana/solana-wallet-service.d.ts +55 -0
  38. package/dist/services/solana/solana-wallet-service.d.ts.map +1 -0
  39. package/dist/services/solana/solana-wallet-service.js +129 -0
  40. package/dist/services/solana/solana-wallet-service.js.map +1 -0
  41. package/dist/services/transaction-service.d.ts +1 -13
  42. package/dist/services/transaction-service.d.ts.map +1 -1
  43. package/dist/services/transaction-service.js +4 -42
  44. package/dist/services/transaction-service.js.map +1 -1
  45. package/package.json +4 -2
  46. package/src/injected-connector.ts +13 -3
  47. package/src/services/connection-manager.ts +2 -2
  48. package/src/services/ethereum/ethereum-transaction-builder.ts +82 -0
  49. package/src/services/ethereum/ethereum-transaction-service.ts +192 -0
  50. package/src/services/{ethereum-wallet-service.ts → ethereum/ethereum-wallet-service.ts} +56 -3
  51. package/src/services/index.ts +3 -3
  52. package/src/services/solana/solana-transaction-builder.ts +214 -0
  53. package/src/services/solana/solana-transaction-service.ts +190 -0
  54. package/src/services/{solana-wallet-service.ts → solana/solana-wallet-service.ts} +2 -2
  55. package/src/services/transaction-service.ts +9 -67
  56. package/dist/injected-connector.old.d.ts +0 -44
  57. package/dist/injected-connector.old.d.ts.map +0 -1
  58. package/dist/injected-connector.old.js +0 -491
  59. package/dist/injected-connector.old.js.map +0 -1
  60. package/dist/providers/evm-provider.d.ts +0 -18
  61. package/dist/providers/evm-provider.d.ts.map +0 -1
  62. package/dist/providers/evm-provider.js +0 -86
  63. package/dist/providers/evm-provider.js.map +0 -1
  64. package/dist/providers/solana-provider.d.ts +0 -22
  65. package/dist/providers/solana-provider.d.ts.map +0 -1
  66. package/dist/providers/solana-provider.js +0 -137
  67. package/dist/providers/solana-provider.js.map +0 -1
  68. package/src/services/ethereum-transaction-service.ts +0 -196
  69. package/src/services/solana-transaction-service.ts +0 -68
@@ -0,0 +1,192 @@
1
+ import { ethers } from 'ethers'
2
+ import type { EthereumProvider } from '../../eip6963-discovery'
3
+ import type {
4
+ EVMNativeTransferRequest,
5
+ EVMContractCallRequest,
6
+ EVMBatchTransactionRequest,
7
+ BatchTransactionResult,
8
+ EthereumTransactionRequest
9
+ } from '@meshconnect/uwc-types'
10
+ import { parseError } from '../../utils/error-utils'
11
+ import { EthereumTransactionBuilder } from './ethereum-transaction-builder'
12
+
13
+ /**
14
+ * Service for handling Ethereum/EVM transaction operations
15
+ */
16
+ export class EthereumTransactionService {
17
+ private builder: EthereumTransactionBuilder
18
+
19
+ constructor() {
20
+ this.builder = new EthereumTransactionBuilder()
21
+ }
22
+
23
+ /**
24
+ * Send a transaction for Ethereum
25
+ */
26
+ async sendTransaction(
27
+ request: EthereumTransactionRequest,
28
+ provider: EthereumProvider
29
+ ): Promise<string> {
30
+ try {
31
+ // Handle different types of EVM transactions
32
+ if ('contractAddress' in request && 'abi' in request) {
33
+ // Contract call
34
+ return await this.sendContractCall(
35
+ provider,
36
+ request as EVMContractCallRequest
37
+ )
38
+ } else if ('calls' in request) {
39
+ // Batch transaction
40
+ return await this.sendBatch(
41
+ provider,
42
+ request as EVMBatchTransactionRequest
43
+ )
44
+ } else if ('amount' in request && typeof request.amount === 'bigint') {
45
+ // Native transfer
46
+ return await this.sendNativeTransaction(
47
+ provider,
48
+ request as EVMNativeTransferRequest
49
+ )
50
+ } else {
51
+ throw new Error('Invalid transaction request type')
52
+ }
53
+ } catch (error) {
54
+ parseError(error)
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Send native token transfer (ETH, BNB, MATIC, etc.)
60
+ */
61
+ private async sendNativeTransaction(
62
+ provider: EthereumProvider,
63
+ request: EVMNativeTransferRequest
64
+ ): Promise<string> {
65
+ try {
66
+ // Build transaction
67
+ const tx = await this.builder.getNativeTransaction(request)
68
+
69
+ // Create ethers provider and signer
70
+ const ethersProvider = new ethers.BrowserProvider(provider)
71
+ const signer = await ethersProvider.getSigner(request.from)
72
+
73
+ // Send transaction
74
+ const response = await signer.sendTransaction(tx)
75
+
76
+ // Wait for confirmation
77
+ const receipt = await response.wait()
78
+ return receipt ? receipt.hash : ''
79
+ } catch (error) {
80
+ parseError(error)
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Send smart contract transaction (including ERC-20 transfers)
86
+ */
87
+ private async sendContractCall(
88
+ provider: EthereumProvider,
89
+ request: EVMContractCallRequest
90
+ ): Promise<string> {
91
+ try {
92
+ // Build transaction
93
+ const tx = await this.builder.getContractTransaction(request)
94
+
95
+ // Create ethers provider and signer
96
+ const ethersProvider = new ethers.BrowserProvider(provider)
97
+ const signer = await ethersProvider.getSigner(request.from)
98
+
99
+ // Send transaction
100
+ const response = await signer.sendTransaction(tx)
101
+
102
+ // Wait for confirmation
103
+ const receipt = await response.wait()
104
+ return receipt ? receipt.hash : ''
105
+ } catch (error) {
106
+ parseError(error)
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Send batch of transactions (EIP-5792)
112
+ */
113
+ private async sendBatch(
114
+ provider: EthereumProvider,
115
+ request: EVMBatchTransactionRequest
116
+ ): Promise<string> {
117
+ try {
118
+ // Prepare calls
119
+ const calls = await Promise.all(
120
+ request.calls.map(async tx => {
121
+ if ('contractAddress' in tx && 'abi' in tx) {
122
+ // Contract call
123
+ const result = await this.builder.getContractTransaction(
124
+ tx as EVMContractCallRequest
125
+ )
126
+ return {
127
+ to: result.to ?? '',
128
+ value: '0x' + (result.value ?? 0n).toString(16),
129
+ data: result.data
130
+ }
131
+ } else if ('amount' in tx && typeof tx.amount === 'bigint') {
132
+ // Native transfer
133
+ const result = await this.builder.getNativeTransaction(
134
+ tx as EVMNativeTransferRequest
135
+ )
136
+ return {
137
+ to: result.to ?? '',
138
+ value: '0x' + (result.value ?? 0n).toString(16)
139
+ }
140
+ } else {
141
+ throw new Error('Invalid transaction request type')
142
+ }
143
+ })
144
+ )
145
+
146
+ // Create ethers provider
147
+ const ethersProvider = new ethers.BrowserProvider(provider)
148
+
149
+ // Send batch transaction
150
+ const response: { id: string } = await ethersProvider.send(
151
+ 'wallet_sendCalls',
152
+ [
153
+ {
154
+ version: request.version,
155
+ from: request.from,
156
+ chainId: request.chainId,
157
+ atomicRequired: request.atomicRequired,
158
+ calls: calls
159
+ }
160
+ ]
161
+ )
162
+
163
+ // Poll for completion
164
+ let result: BatchTransactionResult
165
+ do {
166
+ result = await ethersProvider.send('wallet_getCallsStatus', [
167
+ response.id
168
+ ])
169
+
170
+ // Wait 1 second if still pending
171
+ if (result.status === 100) {
172
+ await new Promise(resolve => setTimeout(resolve, 1000))
173
+ }
174
+ } while (result.status === 100)
175
+
176
+ // Check if successful
177
+ if (result.status !== 200) {
178
+ throw new Error('Batch transaction failed')
179
+ }
180
+
181
+ // Return first transaction hash
182
+ const firstReceipt = result.receipts.find(r => r)
183
+ if (!firstReceipt) {
184
+ throw new Error('No transaction receipt found')
185
+ }
186
+
187
+ return firstReceipt.transactionHash
188
+ } catch (error) {
189
+ parseError(error)
190
+ }
191
+ }
192
+ }
@@ -1,9 +1,14 @@
1
- import type { NetworkId, AvailableAddress } from '@meshconnect/uwc-types'
1
+ import type {
2
+ NetworkId,
3
+ AvailableAddress,
4
+ EVMCapabilities,
5
+ EVMCapabilityStatus
6
+ } from '@meshconnect/uwc-types'
2
7
  import type {
3
8
  EthereumProvider,
4
9
  DetectedWallet as EIP6963DetectedWallet
5
- } from '../eip6963-discovery'
6
- import { getAvailableWallets as getEIP6963Wallets } from '../eip6963-discovery'
10
+ } from '../../eip6963-discovery'
11
+ import { getAvailableWallets as getEIP6963Wallets } from '../../eip6963-discovery'
7
12
 
8
13
  /**
9
14
  * Service for managing Ethereum wallet connections
@@ -158,4 +163,52 @@ export class EthereumWalletService {
158
163
  this.connectedProvider = null
159
164
  this.account = null
160
165
  }
166
+
167
+ /**
168
+ * Get wallet capabilities (EIP-5792 support)
169
+ */
170
+ async getCapabilities(
171
+ from: string
172
+ ): Promise<Record<string, EVMCapabilities>> {
173
+ if (!this.connectedProvider) {
174
+ throw new Error('No Ethereum wallet connected')
175
+ }
176
+
177
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
178
+ let raw: Record<`0x${string}`, Record<string, any>>
179
+ try {
180
+ raw = await this.connectedProvider.request({
181
+ method: 'wallet_getCapabilities',
182
+ params: [from]
183
+ })
184
+ } catch {
185
+ return {}
186
+ }
187
+
188
+ const result: Record<string, EVMCapabilities> = {}
189
+
190
+ for (const [chainId, caps] of Object.entries(raw || {})) {
191
+ const networkId = `eip155:${Number(chainId)}`
192
+ result[networkId] = {}
193
+
194
+ for (const [capKey, capValue] of Object.entries(caps)) {
195
+ if (capValue && typeof capValue === 'object') {
196
+ if (typeof capValue.supported === 'boolean') {
197
+ result[networkId][capKey as keyof EVMCapabilities] = {
198
+ status: capValue.supported ? 'supported' : 'unsupported'
199
+ }
200
+ } else if (
201
+ typeof capValue.status === 'string' &&
202
+ ['supported', 'ready', 'unsupported'].includes(capValue.status)
203
+ ) {
204
+ result[networkId][capKey as keyof EVMCapabilities] = {
205
+ status: capValue.status as EVMCapabilityStatus
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ return result
213
+ }
161
214
  }
@@ -1,7 +1,7 @@
1
1
  export { StorageService } from './storage-service'
2
- export { EthereumWalletService } from './ethereum-wallet-service'
3
- export { SolanaWalletService } from './solana-wallet-service'
2
+ export { EthereumWalletService } from './ethereum/ethereum-wallet-service'
3
+ export { SolanaWalletService } from './solana/solana-wallet-service'
4
4
  export { ConnectionManager } from './connection-manager'
5
5
  export { SignatureService } from './signature-service'
6
6
  export { TransactionService } from './transaction-service'
7
- export { EthereumTransactionService } from './ethereum-transaction-service'
7
+ export { EthereumTransactionService } from './ethereum/ethereum-transaction-service'
@@ -0,0 +1,214 @@
1
+ import {
2
+ AddressLookupTableAccount,
3
+ PublicKey,
4
+ SystemProgram,
5
+ TransactionInstruction,
6
+ TransactionMessage,
7
+ VersionedTransaction,
8
+ type AddressLookupTableState
9
+ } from '@solana/web3.js'
10
+ import type {
11
+ SolanaNativeTransferRequest,
12
+ SolanaTokenTransferRequest,
13
+ SolanaGenericTransferRequest,
14
+ SolanaAccountMeta,
15
+ SolanaTransactionRequest
16
+ } from '@meshconnect/uwc-types'
17
+ import {
18
+ createTransferCheckedInstruction,
19
+ createAssociatedTokenAccountIdempotentInstruction,
20
+ getAssociatedTokenAddress,
21
+ TOKEN_PROGRAM_ID,
22
+ TOKEN_2022_PROGRAM_ID
23
+ } from '@solana/spl-token'
24
+ import { Buffer } from 'buffer'
25
+
26
+ /**
27
+ * Service for handling Solana transaction operations
28
+ */
29
+ export class SolanaTransactionBuilder {
30
+ async buildTransferInstructions(
31
+ request: SolanaTransactionRequest
32
+ ): Promise<TransactionInstruction[]> {
33
+ if ('tokenMint' in request) {
34
+ return await this.buildSplTokenTransferInstructions(
35
+ request as SolanaTokenTransferRequest
36
+ )
37
+ } else if ('instructions' in request) {
38
+ return await this.buildGenericTransferInstructions(
39
+ request as SolanaGenericTransferRequest
40
+ )
41
+ } else {
42
+ return [
43
+ this.buildNativeTransferInstruction(
44
+ request as SolanaNativeTransferRequest
45
+ )
46
+ ]
47
+ }
48
+ }
49
+
50
+ async getVersionedTransaction(
51
+ feePayer: PublicKey,
52
+ request: SolanaTransactionRequest
53
+ ) {
54
+ const lookupTable = this.parseLookupTable(request)
55
+
56
+ return new VersionedTransaction(
57
+ new TransactionMessage({
58
+ payerKey: feePayer,
59
+ recentBlockhash: request.blockhash,
60
+ instructions: await this.buildTransferInstructions(request)
61
+ }).compileToV0Message(lookupTable)
62
+ )
63
+ }
64
+
65
+ /**
66
+ * Build native SOL transfer
67
+ */
68
+ private buildNativeTransferInstruction(
69
+ request: SolanaNativeTransferRequest
70
+ ): TransactionInstruction {
71
+ return SystemProgram.transfer({
72
+ fromPubkey: new PublicKey(request.from),
73
+ toPubkey: new PublicKey(request.to),
74
+ lamports: Number(request.amount)
75
+ })
76
+ }
77
+
78
+ /**
79
+ * Build SPL Token transfer
80
+ */
81
+ private async buildSplTokenTransferInstructions(
82
+ request: SolanaTokenTransferRequest
83
+ ): Promise<TransactionInstruction[]> {
84
+ let instructions: TransactionInstruction[] = []
85
+
86
+ // Create Public Keys
87
+ const mint = new PublicKey(request.tokenMint)
88
+ const from = new PublicKey(request.from)
89
+ const to = new PublicKey(request.to)
90
+
91
+ const fromTokenAccount = await getAssociatedTokenAddress(
92
+ mint,
93
+ from,
94
+ false,
95
+ request.tokenProgram
96
+ ? new PublicKey(request.tokenProgram)
97
+ : TOKEN_PROGRAM_ID
98
+ )
99
+
100
+ const toTokenAccount = await getAssociatedTokenAddress(
101
+ mint,
102
+ to,
103
+ false,
104
+ request.tokenProgram
105
+ ? new PublicKey(request.tokenProgram)
106
+ : TOKEN_PROGRAM_ID
107
+ )
108
+
109
+ // Create target associated token account
110
+ instructions.push(
111
+ createAssociatedTokenAccountIdempotentInstruction(
112
+ from,
113
+ toTokenAccount,
114
+ to,
115
+ mint,
116
+ request.tokenProgram
117
+ ? new PublicKey(request.tokenProgram)
118
+ : TOKEN_PROGRAM_ID
119
+ )
120
+ )
121
+
122
+ const programId =
123
+ request.tokenProgram === TOKEN_2022_PROGRAM_ID.toBase58()
124
+ ? TOKEN_2022_PROGRAM_ID
125
+ : TOKEN_PROGRAM_ID
126
+
127
+ instructions.push(
128
+ createTransferCheckedInstruction(
129
+ fromTokenAccount,
130
+ mint,
131
+ toTokenAccount,
132
+ from,
133
+ request.amount,
134
+ request.tokenDecimals,
135
+ [],
136
+ programId
137
+ )
138
+ )
139
+
140
+ return instructions
141
+ }
142
+
143
+ private async buildGenericTransferInstructions(
144
+ request: SolanaGenericTransferRequest
145
+ ): Promise<TransactionInstruction[]> {
146
+ const result: TransactionInstruction[] = []
147
+
148
+ const instructions = request.instructions
149
+ for (let instrIndex = 0; instrIndex < instructions.length; instrIndex++) {
150
+ const ix = instructions[instrIndex]!
151
+ const programId = new PublicKey(ix.programId)
152
+
153
+ const keys = ix.accounts.map(
154
+ (meta: SolanaAccountMeta, accountIndex: number) => {
155
+ if (!meta.pubKey) {
156
+ throw new Error(
157
+ `Account at instruction ${instrIndex}, index ${accountIndex} has no pubKey and is not fillable`
158
+ )
159
+ }
160
+
161
+ const resolvedPubkey: PublicKey = new PublicKey(meta.pubKey)
162
+ return {
163
+ pubkey: resolvedPubkey,
164
+ isSigner: meta.isSigner,
165
+ isWritable: meta.isWritable
166
+ }
167
+ }
168
+ )
169
+
170
+ result.push(
171
+ new TransactionInstruction({
172
+ keys,
173
+ programId,
174
+ data: Buffer.from(ix.data, 'base64')
175
+ })
176
+ )
177
+ }
178
+
179
+ if (request.additionalRequests) {
180
+ const extraInstructions = await Promise.all(
181
+ request.additionalRequests.map(req =>
182
+ this.buildTransferInstructions(req)
183
+ )
184
+ )
185
+
186
+ result.push(...extraInstructions.flat())
187
+ }
188
+
189
+ return result
190
+ }
191
+
192
+ private parseLookupTable = (
193
+ request: SolanaTransactionRequest
194
+ ): AddressLookupTableAccount[] => {
195
+ if (!('states' in request)) {
196
+ return []
197
+ }
198
+
199
+ return (request.states ?? []).map(state => {
200
+ const currentState: AddressLookupTableState = {
201
+ deactivationSlot: state.deactivationSlot,
202
+ lastExtendedSlot: state.lastExtendedSlot,
203
+ lastExtendedSlotStartIndex: state.lastExtendedStartIndex,
204
+ addresses: [],
205
+ ...(state.authority && { authority: new PublicKey(state.authority) })
206
+ }
207
+
208
+ return new AddressLookupTableAccount({
209
+ key: new PublicKey(state.key),
210
+ state: currentState
211
+ })
212
+ })
213
+ }
214
+ }
@@ -0,0 +1,190 @@
1
+ import { Transaction, Connection } from '@solana/web3.js'
2
+ import type { WalletAdapter } from '@solana/wallet-adapter-base'
3
+ import type {
4
+ SolanaNativeTransferRequest,
5
+ NetworkRpcMap,
6
+ NetworkId,
7
+ SolanaTokenTransferRequest,
8
+ SolanaGenericTransferRequest,
9
+ SolanaTransactionRequest
10
+ } from '@meshconnect/uwc-types'
11
+ import { parseError } from '../../utils/error-utils'
12
+ import { SolanaTransactionBuilder } from './solana-transaction-builder'
13
+
14
+ /**
15
+ * Service for handling Solana transaction operations
16
+ */
17
+ export class SolanaTransactionService {
18
+ private networkRpcMap: NetworkRpcMap
19
+ private builder: SolanaTransactionBuilder
20
+
21
+ constructor(networkRpcMap: NetworkRpcMap = {}) {
22
+ this.networkRpcMap = networkRpcMap
23
+ this.builder = new SolanaTransactionBuilder()
24
+ }
25
+
26
+ /**
27
+ * Send a transaction for Solana
28
+ */
29
+ async sendTransaction(
30
+ request: SolanaTransactionRequest,
31
+ adapter: WalletAdapter
32
+ ): Promise<string> {
33
+ try {
34
+ // Handle different types of Solana transactions
35
+ if ('tokenMint' in request) {
36
+ return await this.sendSplTokenTransaction(
37
+ adapter,
38
+ request as SolanaTokenTransferRequest
39
+ )
40
+ } else if ('from' in request) {
41
+ return await this.sendNativeTransaction(
42
+ adapter,
43
+ request as SolanaNativeTransferRequest
44
+ )
45
+ } else if ('instructions' in request) {
46
+ return await this.sendGenericTransferWithInstructions(
47
+ adapter,
48
+ request as SolanaGenericTransferRequest
49
+ )
50
+ } else {
51
+ throw new Error('Invalid transaction request type')
52
+ }
53
+ } catch (error) {
54
+ parseError(error)
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Send native SOL transfer
60
+ */
61
+ private async sendNativeTransaction(
62
+ adapter: WalletAdapter,
63
+ request: SolanaNativeTransferRequest,
64
+ networkId?: NetworkId
65
+ ): Promise<string> {
66
+ try {
67
+ if (!adapter.publicKey) {
68
+ throw new Error('Wallet not connected')
69
+ }
70
+
71
+ // Verify the from address matches connected wallet
72
+ if (adapter.publicKey.toBase58() !== request.from) {
73
+ throw new Error('From address does not match connected wallet')
74
+ }
75
+
76
+ // Blockhash is required
77
+ if (!request.blockhash) {
78
+ throw new Error('Blockhash is required for Solana transactions')
79
+ }
80
+
81
+ // Create transaction
82
+ const transaction = new Transaction()
83
+ transaction.instructions =
84
+ await this.builder.buildTransferInstructions(request)
85
+
86
+ transaction.recentBlockhash = request.blockhash
87
+ transaction.feePayer = adapter.publicKey
88
+
89
+ // Get RPC URL from the network RPC map or fall back to public endpoint
90
+ const rpcUrl =
91
+ networkId && this.networkRpcMap[networkId]
92
+ ? this.networkRpcMap[networkId]
93
+ : 'https://api.mainnet-beta.solana.com'
94
+ const connection = new Connection(rpcUrl)
95
+
96
+ const signature = await adapter.sendTransaction(transaction, connection)
97
+ return signature
98
+ } catch (error) {
99
+ parseError(error)
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Send SPL token transfer
105
+ */
106
+ private async sendSplTokenTransaction(
107
+ adapter: WalletAdapter,
108
+ request: SolanaTokenTransferRequest,
109
+ networkId?: NetworkId
110
+ ): Promise<string> {
111
+ try {
112
+ if (!adapter.publicKey) {
113
+ throw new Error('Wallet not connected')
114
+ }
115
+
116
+ // Verify the from address matches connected wallet
117
+ if (adapter.publicKey.toBase58() !== request.from) {
118
+ throw new Error('From address does not match connected wallet')
119
+ }
120
+
121
+ // Blockhash is required
122
+ if (!request.blockhash) {
123
+ throw new Error('Blockhash is required for Solana transactions')
124
+ }
125
+
126
+ // Create transaction
127
+ const transaction = new Transaction()
128
+ transaction.instructions =
129
+ await this.builder.buildTransferInstructions(request)
130
+
131
+ transaction.recentBlockhash = request.blockhash
132
+ transaction.feePayer = adapter.publicKey
133
+
134
+ // Get RPC URL from the network RPC map or fall back to public endpoint
135
+ const rpcUrl =
136
+ networkId && this.networkRpcMap[networkId]
137
+ ? this.networkRpcMap[networkId]
138
+ : 'https://api.mainnet-beta.solana.com'
139
+ const connection = new Connection(rpcUrl)
140
+
141
+ const signature = await adapter.sendTransaction(transaction, connection)
142
+ return signature
143
+ } catch (error) {
144
+ parseError(error)
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Send native SOL transfer
150
+ */
151
+ private async sendGenericTransferWithInstructions(
152
+ adapter: WalletAdapter,
153
+ request: SolanaGenericTransferRequest,
154
+ networkId?: NetworkId
155
+ ): Promise<string> {
156
+ try {
157
+ if (!adapter.publicKey) {
158
+ throw new Error('Wallet not connected')
159
+ }
160
+
161
+ // Verify the from address matches connected wallet
162
+ if (adapter.publicKey.toBase58() !== request.feePayer) {
163
+ throw new Error('From address does not match connected wallet')
164
+ }
165
+
166
+ // Blockhash is required
167
+ if (!request.blockhash) {
168
+ throw new Error('Blockhash is required for Solana transactions')
169
+ }
170
+
171
+ // Create transaction
172
+ const transaction = await this.builder.getVersionedTransaction(
173
+ adapter.publicKey,
174
+ request
175
+ )
176
+
177
+ // Get RPC URL from the network RPC map or fall back to public endpoint
178
+ const rpcUrl =
179
+ networkId && this.networkRpcMap[networkId]
180
+ ? this.networkRpcMap[networkId]
181
+ : 'https://api.mainnet-beta.solana.com'
182
+ const connection = new Connection(rpcUrl)
183
+
184
+ const signature = await adapter.sendTransaction(transaction, connection)
185
+ return signature
186
+ } catch (error) {
187
+ parseError(error)
188
+ }
189
+ }
190
+ }
@@ -3,8 +3,8 @@ import type { WalletAdapter } from '@solana/wallet-adapter-base'
3
3
  import {
4
4
  getSolanaWallets,
5
5
  type WalletStandardInfo
6
- } from '../wallet-standard-discovery'
7
- import { StorageService } from './storage-service'
6
+ } from '../../wallet-standard-discovery'
7
+ import { StorageService } from '../storage-service'
8
8
 
9
9
  /**
10
10
  * Service for managing Solana wallet connections