@meshconnect/uwc-wallet-connect-connector 0.2.0 → 0.2.2

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 (32) hide show
  1. package/dist/services/connection-service.d.ts.map +1 -1
  2. package/dist/services/connection-service.js +0 -2
  3. package/dist/services/connection-service.js.map +1 -1
  4. package/dist/services/ethereum/ethereum-transaction-builder.d.ts +14 -0
  5. package/dist/services/ethereum/ethereum-transaction-builder.d.ts.map +1 -0
  6. package/dist/services/ethereum/ethereum-transaction-builder.js +60 -0
  7. package/dist/services/ethereum/ethereum-transaction-builder.js.map +1 -0
  8. package/dist/services/ethereum/ethereum-transaction-service.d.ts +21 -0
  9. package/dist/services/ethereum/ethereum-transaction-service.d.ts.map +1 -0
  10. package/dist/services/ethereum/ethereum-transaction-service.js +107 -0
  11. package/dist/services/ethereum/ethereum-transaction-service.js.map +1 -0
  12. package/dist/services/solana/solana-transaction-builder.d.ts +20 -0
  13. package/dist/services/solana/solana-transaction-builder.d.ts.map +1 -0
  14. package/dist/services/solana/solana-transaction-builder.js +112 -0
  15. package/dist/services/solana/solana-transaction-builder.js.map +1 -0
  16. package/dist/services/solana/solana-transaction-service.d.ts +17 -0
  17. package/dist/services/solana/solana-transaction-service.d.ts.map +1 -0
  18. package/dist/services/solana/solana-transaction-service.js +178 -0
  19. package/dist/services/solana/solana-transaction-service.js.map +1 -0
  20. package/dist/services/transaction-service.d.ts +2 -17
  21. package/dist/services/transaction-service.d.ts.map +1 -1
  22. package/dist/services/transaction-service.js +8 -246
  23. package/dist/services/transaction-service.js.map +1 -1
  24. package/package.json +3 -2
  25. package/src/services/connection-service.ts +0 -3
  26. package/src/services/ethereum/ethereum-transaction-builder.ts +82 -0
  27. package/src/services/ethereum/ethereum-transaction-service.ts +152 -0
  28. package/src/services/solana/solana-transaction-builder.ts +214 -0
  29. package/src/services/solana/solana-transaction-service.ts +294 -0
  30. package/src/services/transaction-service.ts +17 -339
  31. package/src/utils/account-utils.ts +1 -1
  32. package/src/utils/solana-transactions.ts +0 -24
@@ -1,39 +1,30 @@
1
- import { ethers } from 'ethers'
2
- import { Buffer } from 'buffer'
3
- import {
4
- Connection,
5
- PublicKey,
6
- Transaction,
7
- VersionedTransaction
8
- } from '@solana/web3.js'
9
1
  import type {
10
2
  TransactionRequest,
11
3
  TransactionResult,
12
- EVMNativeTransferRequest,
13
- EVMContractCallRequest,
14
- SolanaNativeTransferRequest,
15
- NetworkId,
4
+ EthereumTransactionRequest,
5
+ SolanaTransactionRequest,
16
6
  NetworkRpcMap
17
7
  } from '@meshconnect/uwc-types'
18
- import type SignClient from '@walletconnect/sign-client'
19
8
  import { WalletConnectClient } from './walletconnect-client'
20
9
  import { ConnectionService } from './connection-service'
21
- import { getChainIdFromNetworkId } from '../utils/account-utils'
22
- import { parseError } from '../utils/error-utils'
23
- import { getSolanaTransaction } from '../utils/solana-transactions'
24
- import type { SessionTypes } from '@walletconnect/types'
25
- import base58 from 'bs58'
26
- import { standardizeSignature } from '../utils/encoding-utils'
10
+ import { EthereumTransactionService } from './ethereum/ethereum-transaction-service'
11
+ import { SolanaTransactionService } from './solana/solana-transaction-service'
27
12
 
28
13
  /**
29
14
  * Service for handling transactions in WalletConnect
30
15
  */
31
16
  export class TransactionService {
17
+ private ethereumService: EthereumTransactionService
18
+ private solanaService: SolanaTransactionService
19
+
32
20
  constructor(
33
21
  private walletConnectClient: WalletConnectClient,
34
22
  private connectionService: ConnectionService,
35
- private networkRpcMap: NetworkRpcMap = {}
36
- ) {}
23
+ networkRpcMap: NetworkRpcMap = {}
24
+ ) {
25
+ this.ethereumService = new EthereumTransactionService()
26
+ this.solanaService = new SolanaTransactionService(networkRpcMap)
27
+ }
37
28
 
38
29
  /**
39
30
  * Send a transaction with the connected wallet
@@ -63,18 +54,17 @@ export class TransactionService {
63
54
  const namespace = activeNetwork.id.split(':')[0]
64
55
 
65
56
  if (namespace === 'eip155') {
66
- return this.sendEthereumTransaction(
57
+ return this.ethereumService.sendTransaction(
67
58
  client,
68
59
  session,
69
- request,
70
- activeNetwork.id,
71
- activeAddress
60
+ request as EthereumTransactionRequest,
61
+ activeNetwork.id
72
62
  )
73
63
  } else if (namespace === 'solana') {
74
- return this.sendSolanaTransaction(
64
+ return this.solanaService.sendTransaction(
75
65
  client,
76
66
  session,
77
- request as SolanaNativeTransferRequest,
67
+ request as SolanaTransactionRequest,
78
68
  activeNetwork.id,
79
69
  activeAddress
80
70
  )
@@ -82,316 +72,4 @@ export class TransactionService {
82
72
  throw new Error(`Unsupported namespace: ${namespace}`)
83
73
  }
84
74
  }
85
-
86
- /**
87
- * Send an Ethereum transaction
88
- */
89
- private async sendEthereumTransaction(
90
- client: SignClient,
91
- session: SessionTypes.Struct,
92
- request: TransactionRequest,
93
- activeNetworkId: string,
94
- activeAddress: string
95
- ): Promise<string> {
96
- try {
97
- // Handle different types of EVM transactions
98
- if ('contractAddress' in request && 'abi' in request) {
99
- // Contract call
100
- return await this.sendContractCall(
101
- client,
102
- session,
103
- request as EVMContractCallRequest,
104
- activeNetworkId,
105
- activeAddress
106
- )
107
- } else if ('calls' in request) {
108
- // Batch transaction - not yet supported
109
- throw new Error(
110
- 'Batch transactions are not yet supported for WalletConnect'
111
- )
112
- } else if ('amount' in request && typeof request.amount === 'bigint') {
113
- // Native transfer
114
- return await this.sendNativeTransfer(
115
- client,
116
- session,
117
- request as EVMNativeTransferRequest,
118
- activeNetworkId,
119
- activeAddress
120
- )
121
- } else {
122
- throw new Error('Invalid transaction request type')
123
- }
124
- } catch (error) {
125
- throw parseError(error)
126
- }
127
- }
128
-
129
- /**
130
- * Send a Solana transaction
131
- */
132
- private async sendSolanaTransaction(
133
- client: SignClient,
134
- session: SessionTypes.Struct,
135
- request: SolanaNativeTransferRequest,
136
- activeNetworkId: string,
137
- activeAddress: string
138
- ): Promise<string> {
139
- try {
140
- // Verify the from address matches active address
141
- if (request.from !== activeAddress) {
142
- throw new Error('From address does not match connected wallet')
143
- }
144
-
145
- // Blockhash is required
146
- if (!request.blockhash) {
147
- throw new Error('Blockhash is required for Solana transactions')
148
- }
149
-
150
- // Create the transaction using the utility function
151
- let transaction: Transaction | VersionedTransaction =
152
- getSolanaTransaction(request)
153
-
154
- // Serialize the transaction for WalletConnect
155
- const serializedTransaction = transaction
156
- .serialize({
157
- verifySignatures: false
158
- })
159
- .toString('base64')
160
-
161
- // Get the chain ID (e.g., "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" for mainnet)
162
- const chainId = activeNetworkId
163
-
164
- try {
165
- // First try signAndSendTransaction (preferred method)
166
- const result = await client.request({
167
- topic: session.topic,
168
- chainId,
169
- request: {
170
- method: 'solana_signAndSendTransaction',
171
- params: {
172
- transaction: serializedTransaction
173
- }
174
- }
175
- })
176
-
177
- // WalletConnect returns the signature directly for Solana
178
- return result as string
179
- } catch (signAndSendError: unknown) {
180
- const errorMessage =
181
- signAndSendError instanceof Error
182
- ? signAndSendError.message
183
- : String(signAndSendError)
184
- // If signAndSendTransaction is not supported, fallback to signTransaction
185
- if (
186
- errorMessage.includes('solana_signAndSendTransaction') ||
187
- errorMessage.includes('Missing or invalid')
188
- ) {
189
- // Sign the transaction only
190
- const result: { transaction: string } | { signature: string } =
191
- await client.request({
192
- topic: session.topic,
193
- chainId,
194
- request: {
195
- method: 'solana_signTransaction',
196
- params: {
197
- transaction: serializedTransaction
198
- }
199
- }
200
- })
201
-
202
- if ('signature' in result) {
203
- const decoded = base58.decode(result.signature)
204
- transaction.addSignature(
205
- new PublicKey(request.from),
206
- Buffer.from(decoded) as Buffer & Uint8Array
207
- )
208
- }
209
-
210
- if ('transaction' in result) {
211
- const decodedTransaction = Buffer.from(result.transaction, 'base64')
212
-
213
- if (transaction instanceof VersionedTransaction) {
214
- transaction = VersionedTransaction.deserialize(
215
- new Uint8Array(decodedTransaction)
216
- )
217
- } else {
218
- transaction = Transaction.from(decodedTransaction)
219
- }
220
- }
221
-
222
- // Get RPC URL from the network RPC map or fall back to public endpoint
223
- const rpcUrl =
224
- this.networkRpcMap[activeNetworkId as NetworkId] ||
225
- 'https://api.mainnet-beta.solana.com'
226
- const connection = new Connection(rpcUrl)
227
- const rawSignature = await connection.sendRawTransaction(
228
- transaction.serialize(),
229
- {
230
- skipPreflight: false,
231
- maxRetries: 3,
232
- preflightCommitment: 'confirmed'
233
- }
234
- )
235
-
236
- return standardizeSignature(rawSignature)
237
- }
238
-
239
- // If it's a different error, throw it
240
- throw signAndSendError
241
- }
242
- } catch (error) {
243
- throw parseError(error)
244
- }
245
- }
246
-
247
- /**
248
- * Send native token transfer (ETH, BNB, MATIC, etc.)
249
- */
250
- private async sendNativeTransfer(
251
- client: SignClient,
252
- session: SessionTypes.Struct,
253
- request: EVMNativeTransferRequest,
254
- activeNetworkId: string,
255
- activeAddress: string
256
- ): Promise<string> {
257
- try {
258
- // Use the active network chainId
259
- const chainId = getChainIdFromNetworkId(activeNetworkId as NetworkId)
260
-
261
- // Build transaction using ethers
262
- const tx: ethers.TransactionRequest = {
263
- from: request.from || activeAddress,
264
- to: request.to,
265
- value: request.amount
266
- }
267
-
268
- // Add gas configuration if provided
269
- if (request.gasConfig?.gasLimit) {
270
- tx.gasLimit = BigInt(Math.floor(request.gasConfig.gasLimit))
271
- }
272
- if (request.gasConfig?.maxFeePerGas) {
273
- tx.maxFeePerGas = BigInt(Math.floor(request.gasConfig.maxFeePerGas))
274
- }
275
- if (request.gasConfig?.maxPriorityFeePerGas) {
276
- tx.maxPriorityFeePerGas = BigInt(
277
- Math.floor(request.gasConfig.maxPriorityFeePerGas)
278
- )
279
- }
280
-
281
- // Convert to hex format for WalletConnect
282
- const txParams: Record<string, string> = {
283
- from: tx.from as string,
284
- to: tx.to as string,
285
- value: '0x' + (tx.value ? BigInt(tx.value).toString(16) : '0'),
286
- data: '0x' // Empty data for native transfers
287
- }
288
-
289
- // Add gas params if present
290
- if (tx.gasLimit) {
291
- txParams['gasLimit'] = '0x' + tx.gasLimit.toString(16)
292
- }
293
- if (tx.maxFeePerGas) {
294
- txParams['maxFeePerGas'] = '0x' + tx.maxFeePerGas.toString(16)
295
- }
296
- if (tx.maxPriorityFeePerGas) {
297
- txParams['maxPriorityFeePerGas'] =
298
- '0x' + tx.maxPriorityFeePerGas.toString(16)
299
- }
300
-
301
- const hash = await client.request({
302
- topic: session.topic,
303
- chainId: `eip155:${chainId}`,
304
- request: {
305
- method: 'eth_sendTransaction',
306
- params: [txParams]
307
- }
308
- })
309
-
310
- return hash as string
311
- } catch (error) {
312
- throw parseError(error)
313
- }
314
- }
315
-
316
- /**
317
- * Send smart contract transaction (including ERC-20 transfers)
318
- */
319
- private async sendContractCall(
320
- client: SignClient,
321
- session: SessionTypes.Struct,
322
- request: EVMContractCallRequest,
323
- activeNetworkId: string,
324
- activeAddress: string
325
- ): Promise<string> {
326
- try {
327
- // Use the active network chainId
328
- const chainId = getChainIdFromNetworkId(activeNetworkId as NetworkId)
329
-
330
- // Encode the contract call data using ethers
331
- const iface = new ethers.Interface(request.abi)
332
- const data = iface.encodeFunctionData(request.functionName, request.args)
333
-
334
- // Build transaction using ethers
335
- const tx: ethers.TransactionRequest = {
336
- from: request.from || activeAddress,
337
- to: request.contractAddress,
338
- data
339
- }
340
-
341
- // Add value for payable functions
342
- if (request.value) {
343
- tx.value = BigInt(request.value)
344
- }
345
-
346
- // Add gas configuration if provided
347
- if (request.gasConfig?.gasLimit) {
348
- tx.gasLimit = BigInt(Math.floor(request.gasConfig.gasLimit))
349
- }
350
- if (request.gasConfig?.maxFeePerGas) {
351
- tx.maxFeePerGas = BigInt(Math.floor(request.gasConfig.maxFeePerGas))
352
- }
353
- if (request.gasConfig?.maxPriorityFeePerGas) {
354
- tx.maxPriorityFeePerGas = BigInt(
355
- Math.floor(request.gasConfig.maxPriorityFeePerGas)
356
- )
357
- }
358
-
359
- // Convert to hex format for WalletConnect
360
- const txParams: Record<string, string> = {
361
- from: tx.from as string,
362
- to: tx.to as string,
363
- data: tx.data as string
364
- }
365
-
366
- // Add value if present
367
- if (tx.value) {
368
- txParams['value'] = '0x' + BigInt(tx.value).toString(16)
369
- }
370
-
371
- // Add gas params if present
372
- if (tx.gasLimit) {
373
- txParams['gasLimit'] = '0x' + tx.gasLimit.toString(16)
374
- }
375
- if (tx.maxFeePerGas) {
376
- txParams['maxFeePerGas'] = '0x' + tx.maxFeePerGas.toString(16)
377
- }
378
- if (tx.maxPriorityFeePerGas) {
379
- txParams['maxPriorityFeePerGas'] =
380
- '0x' + tx.maxPriorityFeePerGas.toString(16)
381
- }
382
-
383
- const hash = await client.request({
384
- topic: session.topic,
385
- chainId: `eip155:${chainId}`,
386
- request: {
387
- method: 'eth_sendTransaction',
388
- params: [txParams]
389
- }
390
- })
391
-
392
- return hash as string
393
- } catch (error) {
394
- throw parseError(error)
395
- }
396
- }
397
75
  }
@@ -113,4 +113,4 @@ export function extractAccountsFromNamespaces(
113
113
  })
114
114
 
115
115
  return accounts
116
- }
116
+ }
@@ -1,24 +0,0 @@
1
- import type { SolanaNativeTransferRequest } from '@meshconnect/uwc-types'
2
- import {
3
- PublicKey,
4
- SystemProgram,
5
- Transaction,
6
- VersionedTransaction
7
- } from '@solana/web3.js'
8
-
9
- export function getSolanaTransaction(params: SolanaNativeTransferRequest) {
10
- if (!params.blockhash) {
11
- throw new Error('Blockhash is required for Solana transactions')
12
- }
13
-
14
- const transaction: Transaction | VersionedTransaction = new Transaction().add(
15
- SystemProgram.transfer({
16
- fromPubkey: new PublicKey(params.from),
17
- toPubkey: new PublicKey(params.to),
18
- lamports: Number(params.amount)
19
- })
20
- )
21
- transaction.recentBlockhash = params.blockhash
22
- transaction.feePayer = new PublicKey(params.from)
23
- return transaction
24
- }