@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.
- package/dist/services/connection-service.d.ts.map +1 -1
- package/dist/services/connection-service.js +0 -2
- package/dist/services/connection-service.js.map +1 -1
- package/dist/services/ethereum/ethereum-transaction-builder.d.ts +14 -0
- package/dist/services/ethereum/ethereum-transaction-builder.d.ts.map +1 -0
- package/dist/services/ethereum/ethereum-transaction-builder.js +60 -0
- package/dist/services/ethereum/ethereum-transaction-builder.js.map +1 -0
- package/dist/services/ethereum/ethereum-transaction-service.d.ts +21 -0
- package/dist/services/ethereum/ethereum-transaction-service.d.ts.map +1 -0
- package/dist/services/ethereum/ethereum-transaction-service.js +107 -0
- package/dist/services/ethereum/ethereum-transaction-service.js.map +1 -0
- package/dist/services/solana/solana-transaction-builder.d.ts +20 -0
- package/dist/services/solana/solana-transaction-builder.d.ts.map +1 -0
- package/dist/services/solana/solana-transaction-builder.js +112 -0
- package/dist/services/solana/solana-transaction-builder.js.map +1 -0
- package/dist/services/solana/solana-transaction-service.d.ts +17 -0
- package/dist/services/solana/solana-transaction-service.d.ts.map +1 -0
- package/dist/services/solana/solana-transaction-service.js +178 -0
- package/dist/services/solana/solana-transaction-service.js.map +1 -0
- package/dist/services/transaction-service.d.ts +2 -17
- package/dist/services/transaction-service.d.ts.map +1 -1
- package/dist/services/transaction-service.js +8 -246
- package/dist/services/transaction-service.js.map +1 -1
- package/package.json +3 -2
- package/src/services/connection-service.ts +0 -3
- package/src/services/ethereum/ethereum-transaction-builder.ts +82 -0
- package/src/services/ethereum/ethereum-transaction-service.ts +152 -0
- package/src/services/solana/solana-transaction-builder.ts +214 -0
- package/src/services/solana/solana-transaction-service.ts +294 -0
- package/src/services/transaction-service.ts +17 -339
- package/src/utils/account-utils.ts +1 -1
- package/src/utils/solana-transactions.ts +0 -24
|
@@ -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
|
+
): Promise<VersionedTransaction> {
|
|
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[] | undefined => {
|
|
195
|
+
if (!('states' in request)) {
|
|
196
|
+
return undefined
|
|
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,294 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NetworkId,
|
|
3
|
+
NetworkRpcMap,
|
|
4
|
+
SolanaGenericTransferRequest,
|
|
5
|
+
SolanaNativeTransferRequest,
|
|
6
|
+
SolanaTokenTransferRequest,
|
|
7
|
+
SolanaTransactionRequest
|
|
8
|
+
} from '@meshconnect/uwc-types'
|
|
9
|
+
import {
|
|
10
|
+
VersionedTransaction,
|
|
11
|
+
PublicKey,
|
|
12
|
+
Connection,
|
|
13
|
+
Transaction
|
|
14
|
+
} from '@solana/web3.js'
|
|
15
|
+
import type SignClient from '@walletconnect/sign-client'
|
|
16
|
+
import type { SessionTypes } from '@walletconnect/types'
|
|
17
|
+
import { standardizeSignature } from '../../utils/encoding-utils'
|
|
18
|
+
import { parseError } from '../../utils/error-utils'
|
|
19
|
+
import { Buffer } from 'buffer'
|
|
20
|
+
import base58 from 'bs58'
|
|
21
|
+
import { SolanaTransactionBuilder } from './solana-transaction-builder'
|
|
22
|
+
|
|
23
|
+
export class SolanaTransactionService {
|
|
24
|
+
private builder: SolanaTransactionBuilder
|
|
25
|
+
|
|
26
|
+
constructor(private networkRpcMap: NetworkRpcMap = {}) {
|
|
27
|
+
this.builder = new SolanaTransactionBuilder()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Send a Solana transaction
|
|
32
|
+
*/
|
|
33
|
+
async sendTransaction(
|
|
34
|
+
client: SignClient,
|
|
35
|
+
session: SessionTypes.Struct,
|
|
36
|
+
request: SolanaTransactionRequest,
|
|
37
|
+
activeNetworkId: string,
|
|
38
|
+
activeAddress: string
|
|
39
|
+
): Promise<string> {
|
|
40
|
+
try {
|
|
41
|
+
// Handle different types of Solana transactions
|
|
42
|
+
if ('tokenMint' in request) {
|
|
43
|
+
// SPL token transfer
|
|
44
|
+
return await this.sendSplTokenTransaction(
|
|
45
|
+
client,
|
|
46
|
+
session,
|
|
47
|
+
request as SolanaTokenTransferRequest,
|
|
48
|
+
activeNetworkId,
|
|
49
|
+
activeAddress
|
|
50
|
+
)
|
|
51
|
+
} else if ('instructions' in request) {
|
|
52
|
+
// Generic transaction with instructions
|
|
53
|
+
return await this.sendGenericTransferWithInstructions(
|
|
54
|
+
client,
|
|
55
|
+
session,
|
|
56
|
+
request as SolanaGenericTransferRequest,
|
|
57
|
+
activeNetworkId,
|
|
58
|
+
activeAddress
|
|
59
|
+
)
|
|
60
|
+
} else if ('from' in request) {
|
|
61
|
+
// Native transfer
|
|
62
|
+
return await this.sendNativeTransaction(
|
|
63
|
+
client,
|
|
64
|
+
session,
|
|
65
|
+
request as SolanaNativeTransferRequest,
|
|
66
|
+
activeNetworkId,
|
|
67
|
+
activeAddress
|
|
68
|
+
)
|
|
69
|
+
} else {
|
|
70
|
+
throw new Error('Invalid transaction request type')
|
|
71
|
+
}
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw parseError(error)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private async sendGenericTransferWithInstructions(
|
|
78
|
+
client: SignClient,
|
|
79
|
+
session: SessionTypes.Struct,
|
|
80
|
+
request: SolanaGenericTransferRequest,
|
|
81
|
+
activeNetworkId: string,
|
|
82
|
+
activeAddress: string
|
|
83
|
+
) {
|
|
84
|
+
try {
|
|
85
|
+
if (!activeNetworkId) {
|
|
86
|
+
throw new Error('Active network not found')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Verify the from address matches active address
|
|
90
|
+
if (request.feePayer !== activeAddress) {
|
|
91
|
+
throw new Error('Fee payer address does not match connected wallet')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Blockhash is required
|
|
95
|
+
if (!request.blockhash) {
|
|
96
|
+
throw new Error('Blockhash is required for Solana transactions')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let transaction = await this.builder.getVersionedTransaction(
|
|
100
|
+
new PublicKey(activeAddress),
|
|
101
|
+
request
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return this.submitTransaction(
|
|
105
|
+
client,
|
|
106
|
+
session,
|
|
107
|
+
transaction,
|
|
108
|
+
activeNetworkId,
|
|
109
|
+
activeAddress
|
|
110
|
+
)
|
|
111
|
+
} catch (error) {
|
|
112
|
+
throw parseError(error)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private async sendNativeTransaction(
|
|
117
|
+
client: SignClient,
|
|
118
|
+
session: SessionTypes.Struct,
|
|
119
|
+
request: SolanaNativeTransferRequest,
|
|
120
|
+
activeNetworkId: string,
|
|
121
|
+
activeAddress: string
|
|
122
|
+
) {
|
|
123
|
+
try {
|
|
124
|
+
// Verify the from address matches active address
|
|
125
|
+
if (request.from !== activeAddress) {
|
|
126
|
+
throw new Error('From address does not match connected wallet')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Blockhash is required
|
|
130
|
+
if (!request.blockhash) {
|
|
131
|
+
throw new Error('Blockhash is required for Solana transactions')
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let transaction: Transaction | VersionedTransaction = new Transaction()
|
|
135
|
+
transaction.recentBlockhash = request.blockhash
|
|
136
|
+
transaction.feePayer = new PublicKey(request.from)
|
|
137
|
+
transaction.instructions =
|
|
138
|
+
await this.builder.buildTransferInstructions(request)
|
|
139
|
+
|
|
140
|
+
// Serialize the transaction for WalletConnect
|
|
141
|
+
|
|
142
|
+
return this.submitTransaction(
|
|
143
|
+
client,
|
|
144
|
+
session,
|
|
145
|
+
transaction,
|
|
146
|
+
activeNetworkId,
|
|
147
|
+
activeAddress
|
|
148
|
+
)
|
|
149
|
+
} catch (error) {
|
|
150
|
+
throw parseError(error)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private async sendSplTokenTransaction(
|
|
155
|
+
client: SignClient,
|
|
156
|
+
session: SessionTypes.Struct,
|
|
157
|
+
request: SolanaTokenTransferRequest,
|
|
158
|
+
activeNetworkId: string,
|
|
159
|
+
activeAddress: string
|
|
160
|
+
) {
|
|
161
|
+
try {
|
|
162
|
+
if (!activeNetworkId) {
|
|
163
|
+
throw new Error('Active network not found')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Verify the from address matches active address
|
|
167
|
+
if (request.from !== activeAddress) {
|
|
168
|
+
throw new Error('From address does not match connected wallet')
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Blockhash is required
|
|
172
|
+
if (!request.blockhash) {
|
|
173
|
+
throw new Error('Blockhash is required for Solana transactions')
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let transaction = await this.builder.getVersionedTransaction(
|
|
177
|
+
new PublicKey(activeAddress),
|
|
178
|
+
request
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
return this.submitTransaction(
|
|
182
|
+
client,
|
|
183
|
+
session,
|
|
184
|
+
transaction,
|
|
185
|
+
activeNetworkId,
|
|
186
|
+
activeAddress
|
|
187
|
+
)
|
|
188
|
+
} catch (error) {
|
|
189
|
+
throw parseError(error)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private async submitTransaction(
|
|
194
|
+
client: SignClient,
|
|
195
|
+
session: SessionTypes.Struct,
|
|
196
|
+
transaction: Transaction | VersionedTransaction,
|
|
197
|
+
activeNetworkId: string,
|
|
198
|
+
activeAddress: string
|
|
199
|
+
) {
|
|
200
|
+
// Get the chain ID (e.g., "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" for mainnet)
|
|
201
|
+
const chainId = activeNetworkId
|
|
202
|
+
let serializedTransaction: string
|
|
203
|
+
if (transaction instanceof Transaction) {
|
|
204
|
+
serializedTransaction = transaction
|
|
205
|
+
.serialize({
|
|
206
|
+
verifySignatures: false
|
|
207
|
+
})
|
|
208
|
+
.toString('base64')
|
|
209
|
+
} else {
|
|
210
|
+
serializedTransaction = Buffer.from(
|
|
211
|
+
new Uint8Array(transaction.serialize())
|
|
212
|
+
).toString('base64')
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
// First try signAndSendTransaction (preferred method)
|
|
217
|
+
const result = await client.request({
|
|
218
|
+
topic: session.topic,
|
|
219
|
+
chainId,
|
|
220
|
+
request: {
|
|
221
|
+
method: 'solana_signAndSendTransaction',
|
|
222
|
+
params: {
|
|
223
|
+
transaction: serializedTransaction
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// WalletConnect returns the signature directly for Solana
|
|
229
|
+
return result as string
|
|
230
|
+
} catch (signAndSendError: unknown) {
|
|
231
|
+
const errorMessage =
|
|
232
|
+
signAndSendError instanceof Error
|
|
233
|
+
? signAndSendError.message
|
|
234
|
+
: String(signAndSendError)
|
|
235
|
+
// If signAndSendTransaction is not supported, fallback to signTransaction
|
|
236
|
+
if (
|
|
237
|
+
errorMessage.includes('solana_signAndSendTransaction') ||
|
|
238
|
+
errorMessage.includes('Missing or invalid')
|
|
239
|
+
) {
|
|
240
|
+
// Sign the transaction only
|
|
241
|
+
const result: { transaction: string } | { signature: string } =
|
|
242
|
+
await client.request({
|
|
243
|
+
topic: session.topic,
|
|
244
|
+
chainId,
|
|
245
|
+
request: {
|
|
246
|
+
method: 'solana_signTransaction',
|
|
247
|
+
params: {
|
|
248
|
+
transaction: serializedTransaction
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
if ('signature' in result) {
|
|
254
|
+
const decoded = base58.decode(result.signature)
|
|
255
|
+
transaction.addSignature(
|
|
256
|
+
new PublicKey(activeAddress),
|
|
257
|
+
Buffer.from(decoded) as Buffer & Uint8Array
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if ('transaction' in result) {
|
|
262
|
+
const decodedTransaction = Buffer.from(result.transaction, 'base64')
|
|
263
|
+
|
|
264
|
+
if (transaction instanceof VersionedTransaction) {
|
|
265
|
+
transaction = VersionedTransaction.deserialize(
|
|
266
|
+
new Uint8Array(decodedTransaction)
|
|
267
|
+
)
|
|
268
|
+
} else {
|
|
269
|
+
transaction = Transaction.from(decodedTransaction)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Get RPC URL from the network RPC map or fall back to public endpoint
|
|
274
|
+
const rpcUrl =
|
|
275
|
+
this.networkRpcMap[activeNetworkId as NetworkId] ||
|
|
276
|
+
'https://alien-newest-vineyard.solana-mainnet.quiknode.pro/ebe5e35661d7edb7a5e48ab84bd9d477e472a40b'
|
|
277
|
+
const connection = new Connection(rpcUrl)
|
|
278
|
+
const rawSignature = await connection.sendRawTransaction(
|
|
279
|
+
transaction.serialize(),
|
|
280
|
+
{
|
|
281
|
+
skipPreflight: false,
|
|
282
|
+
maxRetries: 3,
|
|
283
|
+
preflightCommitment: 'confirmed'
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
return standardizeSignature(rawSignature)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// If it's a different error, throw it
|
|
291
|
+
throw signAndSendError
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|