@deserialize/multi-vm-wallet 1.0.2 → 1.0.4
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/IChainWallet.d.ts +17 -0
- package/dist/IChainWallet.js +23 -0
- package/dist/IChainWallet.js.map +1 -0
- package/dist/bip32.d.ts +11 -0
- package/dist/bip32.js +100 -0
- package/dist/bip32.js.map +1 -0
- package/dist/evm/evm.d.ts +56 -0
- package/dist/evm/evm.js +257 -0
- package/dist/evm/evm.js.map +1 -0
- package/dist/evm/index.d.ts +2 -0
- package/dist/evm/index.js +19 -0
- package/dist/evm/index.js.map +1 -0
- package/dist/evm/utils.d.ts +214 -0
- package/dist/evm/utils.js +538 -0
- package/dist/evm/utils.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/old.d.ts +0 -0
- package/dist/old.js +885 -0
- package/dist/old.js.map +1 -0
- package/dist/svm/index.d.ts +1 -0
- package/dist/svm/index.js +18 -0
- package/dist/svm/index.js.map +1 -0
- package/dist/svm/svm.d.ts +37 -0
- package/dist/svm/svm.js +181 -0
- package/dist/svm/svm.js.map +1 -0
- package/dist/svm/transactionSender.d.ts +8 -0
- package/dist/svm/transactionSender.js +88 -0
- package/dist/svm/transactionSender.js.map +1 -0
- package/dist/svm/utils.d.ts +85 -0
- package/dist/svm/utils.js +470 -0
- package/dist/svm/utils.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.js +42 -0
- package/dist/test.js.map +1 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/vm.d.ts +23 -0
- package/dist/vm.js +89 -0
- package/dist/vm.js.map +1 -0
- package/package.json +4 -1
- package/tsconfig.json +11 -111
- package/utils/evm/evm.ts +58 -3
- package/utils/old.ts +1005 -0
- package/utils/svm/svm.ts +29 -12
- package/utils/svm/transactionSender.ts +7 -2
- package/utils/svm/utils.ts +222 -29
- package/utils/test.ts +49 -0
- package/utils/vm.ts +50 -1
package/utils/svm/svm.ts
CHANGED
|
@@ -17,16 +17,25 @@ import {
|
|
|
17
17
|
JupiterQuoteResponse
|
|
18
18
|
} from "./utils";
|
|
19
19
|
import BN from "bn.js";
|
|
20
|
+
import nacl from "tweetnacl";
|
|
21
|
+
import base58 from "bs58";
|
|
20
22
|
|
|
21
23
|
export class SVMVM extends VM<PublicKey, Keypair, Connection> {
|
|
24
|
+
static validateAddress(address: PublicKey): boolean {
|
|
25
|
+
try {
|
|
26
|
+
new PublicKey(address)
|
|
27
|
+
return true
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return false
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
}
|
|
22
33
|
derivationPath = "m/44'/501'/"; // Default SVM derivation path
|
|
23
34
|
|
|
24
35
|
constructor(seed: string) {
|
|
25
36
|
super(seed, "SVM");
|
|
26
37
|
}
|
|
27
|
-
|
|
28
|
-
return PublicKey.isOnCurve(address.toBuffer());
|
|
29
|
-
}
|
|
38
|
+
|
|
30
39
|
static getNativeBalance(address: PublicKey, connection: Connection): Promise<Balance> {
|
|
31
40
|
return getSvmNativeBalance(address, connection);
|
|
32
41
|
}
|
|
@@ -39,6 +48,8 @@ export class SVMVM extends VM<PublicKey, Keypair, Connection> {
|
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
static signAndSendTransaction = signAndSendTransaction
|
|
51
|
+
|
|
52
|
+
|
|
42
53
|
generatePrivateKey(index: number, seed?: string, mnemonic?: string, derivationPath = this.derivationPath) {
|
|
43
54
|
let _seed: string
|
|
44
55
|
|
|
@@ -52,7 +63,8 @@ export class SVMVM extends VM<PublicKey, Keypair, Connection> {
|
|
|
52
63
|
const privateKey = SVMDeriveChildPrivateKey(_seed, index, derivationPath);
|
|
53
64
|
return { privateKey, index };
|
|
54
65
|
}
|
|
55
|
-
static fromMnemonic(
|
|
66
|
+
static fromMnemonic(mnemonic: string): VM<PublicKey, Keypair, Connection> {
|
|
67
|
+
const seed = VM.mnemonicToSeed(mnemonic)
|
|
56
68
|
return new SVMVM(seed)
|
|
57
69
|
}
|
|
58
70
|
|
|
@@ -130,14 +142,14 @@ export class SVMChainWallet extends ChainWallet<PublicKey, Keypair, Connection>
|
|
|
130
142
|
|
|
131
143
|
const baseAmount = uiAmountToBaseUnits(amount, fromToken.decimals);
|
|
132
144
|
|
|
133
|
-
const balance = await this.getTokenBalance(fromTokenMint);
|
|
134
|
-
if (balance.balance.lt(new BN(baseAmount))) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
145
|
+
// const balance = await this.getTokenBalance(fromTokenMint);
|
|
146
|
+
// if (balance.balance.lt(new BN(baseAmount))) {
|
|
147
|
+
// return {
|
|
148
|
+
// success: false,
|
|
149
|
+
// hash: "",
|
|
150
|
+
// error: "Insufficient balance for swap"
|
|
151
|
+
// };
|
|
152
|
+
// }
|
|
141
153
|
|
|
142
154
|
const swapResult = await executeJupiterSwap(
|
|
143
155
|
{
|
|
@@ -209,4 +221,9 @@ export class SVMChainWallet extends ChainWallet<PublicKey, Keypair, Connection>
|
|
|
209
221
|
};
|
|
210
222
|
}
|
|
211
223
|
}
|
|
224
|
+
signMessage = (message: string, signer: Keypair) => {
|
|
225
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
226
|
+
const signature = nacl.sign.detached(messageBytes, signer.secretKey);
|
|
227
|
+
return base58.encode(signature);
|
|
228
|
+
};
|
|
212
229
|
}
|
|
@@ -26,6 +26,7 @@ export async function transactionSenderAndConfirmationWaiter({
|
|
|
26
26
|
serializedTransaction,
|
|
27
27
|
SEND_OPTIONS
|
|
28
28
|
);
|
|
29
|
+
console.log('initial send txid: ', txid);
|
|
29
30
|
|
|
30
31
|
const controller = new AbortController();
|
|
31
32
|
const abortSignal = controller.signal;
|
|
@@ -51,7 +52,8 @@ export async function transactionSenderAndConfirmationWaiter({
|
|
|
51
52
|
blockhashWithExpiryBlockHeight.lastValidBlockHeight - 150;
|
|
52
53
|
|
|
53
54
|
// this would throw TransactionExpiredBlockheightExceededError
|
|
54
|
-
|
|
55
|
+
// console.log("conforming the transaction ....")
|
|
56
|
+
const res = await Promise.race([
|
|
55
57
|
connection.confirmTransaction(
|
|
56
58
|
{
|
|
57
59
|
...blockhashWithExpiryBlockHeight,
|
|
@@ -74,10 +76,13 @@ export async function transactionSenderAndConfirmationWaiter({
|
|
|
74
76
|
}
|
|
75
77
|
}),
|
|
76
78
|
]);
|
|
79
|
+
console.log('res: ', res);
|
|
80
|
+
|
|
77
81
|
} catch (e) {
|
|
82
|
+
console.log('e: ', e);
|
|
78
83
|
if (e instanceof TransactionExpiredBlockheightExceededError) {
|
|
79
84
|
// we consume this error and getTransaction would return null
|
|
80
|
-
return null;
|
|
85
|
+
// return null;
|
|
81
86
|
} else {
|
|
82
87
|
// invalid state from web3.js
|
|
83
88
|
throw e;
|
package/utils/svm/utils.ts
CHANGED
|
@@ -68,8 +68,15 @@ export const createV0Transaction = async (
|
|
|
68
68
|
payerPubKey: PublicKey,
|
|
69
69
|
blockHash?: string
|
|
70
70
|
) => {
|
|
71
|
+
console.log('createV0Transaction: Starting transaction creation');
|
|
72
|
+
console.log('Instructions count:', inX.length);
|
|
73
|
+
console.log('Signers count:', signers.length);
|
|
74
|
+
console.log('Payer public key:', payerPubKey.toString());
|
|
75
|
+
|
|
71
76
|
const blockhash =
|
|
72
77
|
blockHash || (await connection.getLatestBlockhash()).blockhash;
|
|
78
|
+
console.log('Using blockhash:', blockhash);
|
|
79
|
+
|
|
73
80
|
const message = new TransactionMessage({
|
|
74
81
|
payerKey: payerPubKey,
|
|
75
82
|
instructions: inX,
|
|
@@ -79,9 +86,11 @@ export const createV0Transaction = async (
|
|
|
79
86
|
const transaction = new VersionedTransaction(message);
|
|
80
87
|
transaction.message.staticAccountKeys;
|
|
81
88
|
if (signers.length < 1) {
|
|
89
|
+
console.log('Signing transaction with signers');
|
|
82
90
|
transaction.sign(signers);
|
|
83
91
|
}
|
|
84
92
|
|
|
93
|
+
console.log('createV0Transaction: Transaction created successfully');
|
|
85
94
|
return transaction;
|
|
86
95
|
};
|
|
87
96
|
|
|
@@ -91,6 +100,11 @@ export const createAtaAndIx = async (
|
|
|
91
100
|
tokenProgramId: PublicKey,
|
|
92
101
|
connection: Connection,
|
|
93
102
|
) => {
|
|
103
|
+
console.log('createAtaAndIx: Starting ATA creation');
|
|
104
|
+
console.log('Token:', token.toString());
|
|
105
|
+
console.log('Owner:', ownerPublicKey.toString());
|
|
106
|
+
console.log('Token Program ID:', tokenProgramId.toString());
|
|
107
|
+
|
|
94
108
|
let AtaTokenIx;
|
|
95
109
|
const associatedToken = getAssociatedTokenAddressSync(
|
|
96
110
|
token,
|
|
@@ -98,9 +112,11 @@ export const createAtaAndIx = async (
|
|
|
98
112
|
false,
|
|
99
113
|
tokenProgramId
|
|
100
114
|
);
|
|
115
|
+
console.log('Associated token address:', associatedToken.toString());
|
|
101
116
|
|
|
102
117
|
const accountExist = await connection.getAccountInfo(associatedToken);
|
|
103
118
|
if (!accountExist) {
|
|
119
|
+
console.log('Account does not exist, creating ATA instruction');
|
|
104
120
|
AtaTokenIx = createAssociatedTokenAccountIdempotentInstruction(
|
|
105
121
|
ownerPublicKey,
|
|
106
122
|
associatedToken,
|
|
@@ -108,17 +124,26 @@ export const createAtaAndIx = async (
|
|
|
108
124
|
token,
|
|
109
125
|
tokenProgramId
|
|
110
126
|
);
|
|
127
|
+
} else {
|
|
128
|
+
console.log('Account already exists, no ATA instruction needed');
|
|
111
129
|
}
|
|
130
|
+
|
|
131
|
+
console.log('createAtaAndIx: Completed');
|
|
112
132
|
return {
|
|
113
133
|
AtaTokenIx,
|
|
114
134
|
associatedToken,
|
|
115
135
|
};
|
|
116
136
|
};
|
|
137
|
+
|
|
117
138
|
export const getSureAssociatedTokenAddressAndAccount = async (
|
|
118
139
|
connection: Connection,
|
|
119
140
|
token: PublicKey,
|
|
120
141
|
owner: PublicKey,
|
|
121
142
|
) => {
|
|
143
|
+
console.log('getSureAssociatedTokenAddressAndAccount: Starting');
|
|
144
|
+
console.log('Token:', token.toString());
|
|
145
|
+
console.log('Owner:', owner.toString());
|
|
146
|
+
|
|
122
147
|
let ATA: PublicKey;
|
|
123
148
|
let programId: PublicKey;
|
|
124
149
|
let tokenAccount: Account;
|
|
@@ -126,90 +151,128 @@ export const getSureAssociatedTokenAddressAndAccount = async (
|
|
|
126
151
|
programId = token.equals(NATIVE_MINT)
|
|
127
152
|
? TOKEN_PROGRAM_ID
|
|
128
153
|
: TOKEN_2022_PROGRAM_ID;
|
|
154
|
+
console.log('Trying with program ID:', programId.toString());
|
|
155
|
+
|
|
129
156
|
ATA = getAssociatedTokenAddressSync(token, owner, true, programId);
|
|
157
|
+
console.log('ATA address:', ATA.toString());
|
|
158
|
+
|
|
130
159
|
tokenAccount = await getAccount(connection, ATA, "confirmed", programId);
|
|
160
|
+
console.log('Token account found with TOKEN_2022_PROGRAM_ID');
|
|
131
161
|
return { ATA, programId, tokenAccount };
|
|
132
162
|
} catch (error) {
|
|
163
|
+
console.log('Failed with TOKEN_2022_PROGRAM_ID, trying TOKEN_PROGRAM_ID');
|
|
164
|
+
console.log('Error:', error);
|
|
165
|
+
|
|
133
166
|
programId = TOKEN_PROGRAM_ID;
|
|
134
167
|
ATA = getAssociatedTokenAddressSync(token, owner, true, programId);
|
|
168
|
+
console.log('New ATA address:', ATA.toString());
|
|
169
|
+
|
|
135
170
|
tokenAccount = await getAccount(connection, ATA, "confirmed", programId);
|
|
171
|
+
console.log('Token account found with TOKEN_PROGRAM_ID');
|
|
136
172
|
return { ATA, programId, tokenAccount };
|
|
137
173
|
}
|
|
138
174
|
};
|
|
139
175
|
|
|
140
176
|
export const getProgramIdOfToken = async (owner: PublicKey, token: PublicKey, connection: Connection) => {
|
|
177
|
+
console.log('getProgramIdOfToken: Starting');
|
|
178
|
+
console.log('Owner:', owner.toString());
|
|
179
|
+
console.log('Token:', token.toString());
|
|
180
|
+
|
|
141
181
|
if (token.equals(NATIVE_MINT)) {
|
|
182
|
+
console.log('Token is native mint, returning TOKEN_PROGRAM_ID');
|
|
142
183
|
return TOKEN_PROGRAM_ID;
|
|
143
184
|
}
|
|
144
185
|
let ATA: PublicKey;
|
|
145
186
|
let programId: PublicKey = TOKEN_PROGRAM_ID
|
|
146
187
|
let tokenAccount: Account;
|
|
147
188
|
try {
|
|
189
|
+
console.log('Trying with TOKEN_PROGRAM_ID');
|
|
148
190
|
ATA = getAssociatedTokenAddressSync(token, owner, true, programId);
|
|
149
191
|
tokenAccount = await getAccount(connection, ATA, "confirmed", programId);
|
|
192
|
+
console.log('Found with TOKEN_PROGRAM_ID');
|
|
150
193
|
return TOKEN_PROGRAM_ID
|
|
151
194
|
} catch (error) {
|
|
195
|
+
console.log('Failed with TOKEN_PROGRAM_ID, returning TOKEN_2022_PROGRAM_ID');
|
|
196
|
+
console.log('Error:', error);
|
|
152
197
|
return TOKEN_2022_PROGRAM_ID;
|
|
153
|
-
|
|
154
198
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
199
|
}
|
|
159
|
-
//get native balance
|
|
160
200
|
|
|
201
|
+
//get native balance
|
|
161
202
|
export const getSvmNativeBalance = async (address: PublicKey, connection: Connection,) => {
|
|
203
|
+
console.log('getSvmNativeBalance: Getting balance for', address.toString());
|
|
162
204
|
const balance = await connection.getBalance(address);
|
|
205
|
+
console.log('Raw balance:', balance);
|
|
206
|
+
console.log('Formatted balance:', balance / LAMPORTS_PER_SOL, 'SOL');
|
|
163
207
|
return { balance: new BN(balance), formatted: balance / LAMPORTS_PER_SOL, decimal: 9 };
|
|
164
208
|
};
|
|
165
209
|
|
|
166
210
|
export const getTokenBalance = async (address: PublicKey, token: PublicKey, connection: Connection) => {
|
|
211
|
+
console.log('getTokenBalance: Starting');
|
|
212
|
+
console.log('Address:', address.toString());
|
|
213
|
+
console.log('Token:', token.toString());
|
|
167
214
|
|
|
168
215
|
try {
|
|
169
216
|
// Get the balance from the token account
|
|
170
217
|
const tokenAccount = await getTokenAccountAccount(token, address, connection);
|
|
171
218
|
if (!tokenAccount) {
|
|
172
|
-
console.
|
|
219
|
+
console.log("Token account not found");
|
|
173
220
|
return 0;
|
|
174
221
|
}
|
|
222
|
+
console.log('Token account found:', tokenAccount.address.toString());
|
|
223
|
+
|
|
175
224
|
const tokenBalance = await connection.getTokenAccountBalance(
|
|
176
225
|
tokenAccount.address
|
|
177
226
|
);
|
|
178
227
|
|
|
179
228
|
if (!tokenBalance) {
|
|
180
|
-
console.
|
|
229
|
+
console.log("Token balance not found");
|
|
181
230
|
return 0;
|
|
182
231
|
}
|
|
183
232
|
|
|
233
|
+
console.log('Token balance:', tokenBalance.value);
|
|
184
234
|
return tokenBalance.value;
|
|
185
235
|
|
|
186
236
|
} catch (error) {
|
|
237
|
+
console.log('Error in getTokenBalance:', error);
|
|
187
238
|
return 0;
|
|
188
239
|
}
|
|
189
240
|
}
|
|
190
241
|
|
|
191
242
|
export const getTokenAccountAccount = async (token: PublicKey, address: PublicKey, connection: Connection): Promise<Account | null> => {
|
|
192
|
-
|
|
243
|
+
console.log('getTokenAccountAccount: Starting');
|
|
244
|
+
console.log('Token:', token.toString());
|
|
245
|
+
console.log('Address:', address.toString());
|
|
193
246
|
|
|
247
|
+
try {
|
|
194
248
|
// Get the associated token account address for the user and the token mint
|
|
195
249
|
const associatedTokenAccount = await getAssociatedTokenAddress(
|
|
196
250
|
token, // The token mint address
|
|
197
251
|
address // The user's public key
|
|
198
252
|
);
|
|
253
|
+
console.log('Associated token account:', associatedTokenAccount.toString());
|
|
254
|
+
|
|
199
255
|
// Fetch the token account information
|
|
200
256
|
const tokenAccount = await getAccount(
|
|
201
257
|
connection,
|
|
202
258
|
associatedTokenAccount
|
|
203
259
|
);
|
|
204
260
|
|
|
261
|
+
console.log('Token account retrieved successfully');
|
|
205
262
|
return tokenAccount;
|
|
206
263
|
} catch (error) {
|
|
207
|
-
console.
|
|
264
|
+
console.log("Error getting token account:", error);
|
|
208
265
|
return null;
|
|
209
266
|
}
|
|
210
267
|
};
|
|
211
268
|
|
|
212
269
|
export const getTransferNativeInx = async (from: PublicKey, to: PublicKey, amount: number): Promise<TransactionInstruction> => {
|
|
270
|
+
console.log('getTransferNativeInx: Creating transfer instruction');
|
|
271
|
+
console.log('From:', from.toString());
|
|
272
|
+
console.log('To:', to.toString());
|
|
273
|
+
console.log('Amount:', amount, 'SOL');
|
|
274
|
+
console.log('Lamports:', amount * LAMPORTS_PER_SOL);
|
|
275
|
+
|
|
213
276
|
return SystemProgram.transfer({
|
|
214
277
|
fromPubkey: from,
|
|
215
278
|
toPubkey: to,
|
|
@@ -218,48 +281,86 @@ export const getTransferNativeInx = async (from: PublicKey, to: PublicKey, amoun
|
|
|
218
281
|
}
|
|
219
282
|
|
|
220
283
|
export const getTransferNativeTransaction = async (from: Keypair, to: PublicKey, amount: number, connection: Connection) => {
|
|
284
|
+
console.log('getTransferNativeTransaction: Starting');
|
|
221
285
|
const instruction = await getTransferNativeInx(from.publicKey, to, amount);
|
|
222
286
|
const transaction = await createV0Transaction(connection, [instruction], [from], from.publicKey);
|
|
287
|
+
console.log('getTransferNativeTransaction: Completed');
|
|
223
288
|
return transaction;
|
|
224
289
|
}
|
|
225
290
|
|
|
226
291
|
export const getTransferTokenInx = async (from: PublicKey, to: PublicKey, token: TokenInfo, amount: number, connection: Connection): Promise<TransactionInstruction[]> => {
|
|
292
|
+
console.log('getTransferTokenInx: Starting');
|
|
293
|
+
console.log('From:', from.toString());
|
|
294
|
+
console.log('To:', to.toString());
|
|
295
|
+
console.log('Token:', token);
|
|
296
|
+
console.log('Amount:', amount);
|
|
297
|
+
|
|
227
298
|
const inx: TransactionInstruction[] = []
|
|
228
299
|
|
|
229
300
|
const tokenToSend = new PublicKey(token.address);
|
|
301
|
+
console.log('Token to send:', tokenToSend.toString());
|
|
302
|
+
|
|
230
303
|
const { ATA: source, programId, tokenAccount } = await getSureAssociatedTokenAddressAndAccount(connection, from, tokenToSend);
|
|
304
|
+
console.log('Source ATA:', source.toString());
|
|
305
|
+
|
|
231
306
|
const { associatedToken: destination, AtaTokenIx } = await createAtaAndIx(tokenToSend, to, programId, connection);
|
|
307
|
+
console.log('Destination ATA:', destination.toString());
|
|
232
308
|
|
|
233
309
|
if (!tokenAccount) {
|
|
310
|
+
console.log('Token account not found, throwing error');
|
|
234
311
|
throw new Error("Token account not found");
|
|
235
312
|
}
|
|
236
313
|
if (AtaTokenIx) {
|
|
314
|
+
console.log('Adding ATA creation instruction');
|
|
237
315
|
inx.push(AtaTokenIx);
|
|
238
316
|
}
|
|
317
|
+
|
|
318
|
+
console.log('Creating transfer instruction');
|
|
239
319
|
const tInx = createTransferCheckedInstruction(source, tokenToSend, destination, from, amount, token.decimals, undefined, programId)
|
|
240
320
|
inx.push(tInx);
|
|
241
321
|
|
|
322
|
+
console.log('getTransferTokenInx: Completed with', inx.length, 'instructions');
|
|
242
323
|
return inx;
|
|
243
|
-
|
|
244
324
|
}
|
|
325
|
+
|
|
245
326
|
export const getTransferTokenTransaction = async (from: Keypair, to: PublicKey, token: TokenInfo, amount: number, connection: Connection): Promise<VersionedTransaction> => {
|
|
327
|
+
console.log('getTransferTokenTransaction: Starting');
|
|
246
328
|
const instruction = await getTransferTokenInx(from.publicKey, to, token, amount, connection);
|
|
247
329
|
const transaction = await createV0Transaction(connection, instruction, [from], from.publicKey);
|
|
330
|
+
console.log('getTransferTokenTransaction: Completed');
|
|
248
331
|
return transaction;
|
|
249
332
|
}
|
|
333
|
+
|
|
250
334
|
export const signAndSendTransaction = async (transaction: VersionedTransaction, connection: Connection, signers: Keypair[]) => {
|
|
335
|
+
console.log('signAndSendTransaction: Starting');
|
|
336
|
+
console.log('Signers count:', signers.length);
|
|
337
|
+
|
|
251
338
|
transaction.sign(signers)
|
|
339
|
+
console.log('Transaction signed');
|
|
340
|
+
|
|
252
341
|
const blockhash = await connection.getLatestBlockhash()
|
|
253
|
-
|
|
342
|
+
console.log('Got latest blockhash:', blockhash.blockhash);
|
|
343
|
+
|
|
344
|
+
console.log('Sending transaction...');
|
|
345
|
+
const res = await transactionSenderAndConfirmationWaiter({
|
|
346
|
+
connection,
|
|
347
|
+
serializedTransaction: Buffer.from(transaction.serialize()),
|
|
348
|
+
blockhashWithExpiryBlockHeight: {
|
|
349
|
+
blockhash: blockhash.blockhash,
|
|
350
|
+
lastValidBlockHeight: blockhash.lastValidBlockHeight
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
|
|
254
354
|
if (!res) {
|
|
355
|
+
console.log('Transaction failed to send or confirm');
|
|
255
356
|
throw new Error("Transaction failed to send or confirm");
|
|
256
357
|
}
|
|
257
|
-
return res.transaction.signatures[0];
|
|
258
358
|
|
|
359
|
+
const signature = res.transaction.signatures[0];
|
|
360
|
+
console.log('Transaction successful, signature:', signature);
|
|
361
|
+
return signature;
|
|
259
362
|
}
|
|
260
363
|
|
|
261
|
-
|
|
262
|
-
|
|
263
364
|
//swap
|
|
264
365
|
//you will. use jupiter for this
|
|
265
366
|
|
|
@@ -269,6 +370,12 @@ export const getJupiterQuote = async (
|
|
|
269
370
|
amount: number,
|
|
270
371
|
slippageBps: number = 50
|
|
271
372
|
): Promise<JupiterQuoteResponse> => {
|
|
373
|
+
console.log('getJupiterQuote: Starting');
|
|
374
|
+
console.log('Input mint:', inputMint);
|
|
375
|
+
console.log('Output mint:', outputMint);
|
|
376
|
+
console.log('Amount:', amount);
|
|
377
|
+
console.log('Slippage BPS:', slippageBps);
|
|
378
|
+
|
|
272
379
|
const params = new URLSearchParams({
|
|
273
380
|
inputMint,
|
|
274
381
|
outputMint,
|
|
@@ -278,14 +385,34 @@ export const getJupiterQuote = async (
|
|
|
278
385
|
asLegacyTransaction: 'false'
|
|
279
386
|
});
|
|
280
387
|
|
|
281
|
-
const
|
|
388
|
+
const url = `${JUPITER_BASE_URL}/swap/v1/quote?${params}`;
|
|
389
|
+
console.log('Request URL:', url);
|
|
390
|
+
|
|
391
|
+
const response = await fetch(url);
|
|
392
|
+
console.log('Response status:', response.status);
|
|
393
|
+
console.log('Response status text:', response.statusText);
|
|
282
394
|
|
|
283
395
|
if (!response.ok) {
|
|
284
|
-
|
|
285
|
-
|
|
396
|
+
console.log('Jupiter quote request failed');
|
|
397
|
+
console.log('Status:', response.status);
|
|
398
|
+
console.log('Status Text:', response.statusText);
|
|
399
|
+
console.log('URL:', url);
|
|
400
|
+
|
|
401
|
+
try {
|
|
402
|
+
const error = await response.json();
|
|
403
|
+
console.log('Error details:', error);
|
|
404
|
+
} catch {
|
|
405
|
+
const textError = await response.text();
|
|
406
|
+
console.log('Error text:', textError);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
throw new Error(`Jupiter quote failed: ${response.statusText}`);
|
|
286
410
|
}
|
|
287
411
|
|
|
288
|
-
|
|
412
|
+
const result = await response.json();
|
|
413
|
+
console.log('Jupiter quote successful');
|
|
414
|
+
console.log('Quote result:', result);
|
|
415
|
+
return result;
|
|
289
416
|
};
|
|
290
417
|
|
|
291
418
|
export const buildJupiterSwapTransaction = async (
|
|
@@ -293,6 +420,10 @@ export const buildJupiterSwapTransaction = async (
|
|
|
293
420
|
userPublicKey: string,
|
|
294
421
|
prioritizationFeeLamports?: number
|
|
295
422
|
): Promise<JupiterSwapResponse> => {
|
|
423
|
+
console.log('buildJupiterSwapTransaction: Starting');
|
|
424
|
+
console.log('User public key:', userPublicKey);
|
|
425
|
+
const priorityFee = prioritizationFeeLamports || 5000;
|
|
426
|
+
console.log('Prioritization fee:', priorityFee);
|
|
296
427
|
const body = {
|
|
297
428
|
quoteResponse: quote,
|
|
298
429
|
userPublicKey,
|
|
@@ -301,7 +432,7 @@ export const buildJupiterSwapTransaction = async (
|
|
|
301
432
|
feeAccount: undefined,
|
|
302
433
|
trackingAccount: undefined,
|
|
303
434
|
computeUnitPriceMicroLamports: undefined,
|
|
304
|
-
prioritizationFeeLamports:
|
|
435
|
+
prioritizationFeeLamports: priorityFee,
|
|
305
436
|
asLegacyTransaction: false,
|
|
306
437
|
useTokenLedger: false,
|
|
307
438
|
destinationTokenAccount: undefined,
|
|
@@ -309,6 +440,8 @@ export const buildJupiterSwapTransaction = async (
|
|
|
309
440
|
skipUserAccountsRpcCalls: false
|
|
310
441
|
};
|
|
311
442
|
|
|
443
|
+
console.log('Request body:', body);
|
|
444
|
+
|
|
312
445
|
const response = await fetch(`${JUPITER_BASE_URL}/swap/v1/swap`, {
|
|
313
446
|
method: 'POST',
|
|
314
447
|
headers: {
|
|
@@ -317,12 +450,26 @@ export const buildJupiterSwapTransaction = async (
|
|
|
317
450
|
body: JSON.stringify(body),
|
|
318
451
|
});
|
|
319
452
|
|
|
453
|
+
console.log('Swap transaction build response status:', response.status);
|
|
454
|
+
|
|
320
455
|
if (!response.ok) {
|
|
321
|
-
|
|
322
|
-
|
|
456
|
+
console.log('Jupiter swap transaction build failed');
|
|
457
|
+
console.log('Status:', response.status);
|
|
458
|
+
console.log('Status text:', response.statusText);
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
const error = await response.json();
|
|
462
|
+
console.log('Swap build error details:', error);
|
|
463
|
+
throw new Error(`Jupiter swap transaction build failed: ${error.message || response.statusText}`);
|
|
464
|
+
} catch (parseError) {
|
|
465
|
+
console.log('Failed to parse error response:', parseError);
|
|
466
|
+
throw new Error(`Jupiter swap transaction build failed: ${response.statusText}`);
|
|
467
|
+
}
|
|
323
468
|
}
|
|
324
469
|
|
|
325
|
-
|
|
470
|
+
const result = await response.json();
|
|
471
|
+
console.log('Jupiter swap transaction built successfully');
|
|
472
|
+
return result;
|
|
326
473
|
};
|
|
327
474
|
|
|
328
475
|
export const executeJupiterSwap = async (
|
|
@@ -330,6 +477,15 @@ export const executeJupiterSwap = async (
|
|
|
330
477
|
connection: Connection,
|
|
331
478
|
payer: Keypair
|
|
332
479
|
): Promise<SwapResult> => {
|
|
480
|
+
console.log('executeJupiterSwap: Starting');
|
|
481
|
+
console.log('Swap params:', {
|
|
482
|
+
fromToken: swapParams.fromToken.toString(),
|
|
483
|
+
toToken: swapParams.toToken.toString(),
|
|
484
|
+
amount: swapParams.amount,
|
|
485
|
+
slippageBps: swapParams.slippageBps,
|
|
486
|
+
userPublicKey: swapParams.userPublicKey.toString()
|
|
487
|
+
});
|
|
488
|
+
|
|
333
489
|
try {
|
|
334
490
|
console.log('Getting Jupiter quote...');
|
|
335
491
|
const quote = await getJupiterQuote(
|
|
@@ -353,13 +509,19 @@ export const executeJupiterSwap = async (
|
|
|
353
509
|
|
|
354
510
|
console.log('Deserializing transaction...');
|
|
355
511
|
const swapTransactionBuf = Buffer.from(swapResponse.swapTransaction, 'base64');
|
|
512
|
+
console.log('Transaction buffer length:', swapTransactionBuf.length);
|
|
513
|
+
|
|
356
514
|
const transaction = VersionedTransaction.deserialize(swapTransactionBuf);
|
|
515
|
+
console.log('Transaction deserialized successfully');
|
|
357
516
|
|
|
358
517
|
console.log('Signing transaction...');
|
|
359
518
|
transaction.sign([payer]);
|
|
519
|
+
console.log('Transaction signed');
|
|
360
520
|
|
|
361
521
|
console.log('Sending transaction...');
|
|
362
522
|
const blockhash = await connection.getLatestBlockhash();
|
|
523
|
+
console.log('Got latest blockhash for confirmation');
|
|
524
|
+
|
|
363
525
|
const signature = await transactionSenderAndConfirmationWaiter({
|
|
364
526
|
connection,
|
|
365
527
|
serializedTransaction: Buffer.from(transaction.serialize()),
|
|
@@ -369,25 +531,32 @@ export const executeJupiterSwap = async (
|
|
|
369
531
|
}
|
|
370
532
|
});
|
|
371
533
|
|
|
534
|
+
// console.log('signature: ', signature);
|
|
372
535
|
if (!signature) {
|
|
536
|
+
console.log('Transaction failed to confirm');
|
|
373
537
|
return {
|
|
374
538
|
success: false,
|
|
375
539
|
error: 'Transaction failed to confirm'
|
|
376
540
|
};
|
|
377
541
|
}
|
|
378
542
|
|
|
379
|
-
|
|
543
|
+
const txSignature = signature.transaction.signatures[0];
|
|
544
|
+
console.log('Swap successful! Signature:', txSignature);
|
|
380
545
|
|
|
381
546
|
return {
|
|
382
547
|
success: true,
|
|
383
|
-
hash:
|
|
548
|
+
hash: txSignature,
|
|
384
549
|
inputAmount: quote.inAmount,
|
|
385
550
|
outputAmount: quote.outAmount,
|
|
386
551
|
priceImpact: quote.priceImpactPct
|
|
387
552
|
};
|
|
388
553
|
|
|
389
554
|
} catch (error) {
|
|
390
|
-
console.
|
|
555
|
+
console.log('Jupiter swap failed with error:', error);
|
|
556
|
+
console.log('Error type:', typeof error);
|
|
557
|
+
console.log('Error message:', error instanceof Error ? error.message : 'Unknown error');
|
|
558
|
+
console.log('Error stack:', error instanceof Error ? error.stack : 'No stack trace');
|
|
559
|
+
|
|
391
560
|
return {
|
|
392
561
|
success: false,
|
|
393
562
|
error: error instanceof Error ? error.message : 'Unknown error occurred'
|
|
@@ -396,22 +565,34 @@ export const executeJupiterSwap = async (
|
|
|
396
565
|
};
|
|
397
566
|
|
|
398
567
|
export const uiAmountToBaseUnits = (uiAmount: number, decimals: number): number => {
|
|
399
|
-
|
|
568
|
+
console.log('uiAmountToBaseUnits: Converting', uiAmount, 'with', decimals, 'decimals');
|
|
569
|
+
const result = Math.floor(uiAmount * Math.pow(10, decimals));
|
|
570
|
+
console.log('Converted to base units:', result);
|
|
571
|
+
return result;
|
|
400
572
|
};
|
|
401
573
|
|
|
402
574
|
export const baseUnitsToUiAmount = (baseAmount: string | number, decimals: number): number => {
|
|
403
|
-
|
|
575
|
+
console.log('baseUnitsToUiAmount: Converting', baseAmount, 'with', decimals, 'decimals');
|
|
576
|
+
const result = Number(baseAmount) / Math.pow(10, decimals);
|
|
577
|
+
console.log('Converted to UI amount:', result);
|
|
578
|
+
return result;
|
|
404
579
|
};
|
|
405
580
|
|
|
406
581
|
export const getJupiterTokenList = async (): Promise<any[]> => {
|
|
582
|
+
console.log('getJupiterTokenList: Fetching token list');
|
|
407
583
|
try {
|
|
408
584
|
const response = await fetch(`${JUPITER_BASE_URL}/tokens/v1/mints/tradable`);
|
|
585
|
+
console.log('Token list response status:', response.status);
|
|
586
|
+
|
|
409
587
|
if (!response.ok) {
|
|
588
|
+
console.log('Failed to fetch token list:', response.statusText);
|
|
410
589
|
throw new Error(`Failed to fetch token list: ${response.statusText}`);
|
|
411
590
|
}
|
|
412
|
-
|
|
591
|
+
const result = await response.json();
|
|
592
|
+
console.log('Token list fetched, count:', result.length);
|
|
593
|
+
return result;
|
|
413
594
|
} catch (error) {
|
|
414
|
-
console.
|
|
595
|
+
console.log('Failed to fetch Jupiter token list:', error);
|
|
415
596
|
return [];
|
|
416
597
|
}
|
|
417
598
|
};
|
|
@@ -420,23 +601,35 @@ export const validateJupiterTokens = async (
|
|
|
420
601
|
inputMint: string,
|
|
421
602
|
outputMint: string
|
|
422
603
|
): Promise<{ valid: boolean; message?: string }> => {
|
|
604
|
+
console.log('validateJupiterTokens: Starting validation');
|
|
605
|
+
console.log('Input mint:', inputMint);
|
|
606
|
+
console.log('Output mint:', outputMint);
|
|
607
|
+
|
|
423
608
|
try {
|
|
424
609
|
const tokenList = await getJupiterTokenList();
|
|
425
610
|
const inputSupported = tokenList.includes(inputMint);
|
|
426
611
|
const outputSupported = tokenList.includes(outputMint);
|
|
427
612
|
|
|
613
|
+
console.log('Input token supported:', inputSupported);
|
|
614
|
+
console.log('Output token supported:', outputSupported);
|
|
615
|
+
|
|
428
616
|
if (!inputSupported && !outputSupported) {
|
|
617
|
+
console.log('Both tokens not supported');
|
|
429
618
|
return { valid: false, message: 'Both input and output tokens are not supported' };
|
|
430
619
|
}
|
|
431
620
|
if (!inputSupported) {
|
|
621
|
+
console.log('Input token not supported');
|
|
432
622
|
return { valid: false, message: 'Input token is not supported' };
|
|
433
623
|
}
|
|
434
624
|
if (!outputSupported) {
|
|
625
|
+
console.log('Output token not supported');
|
|
435
626
|
return { valid: false, message: 'Output token is not supported' };
|
|
436
627
|
}
|
|
437
628
|
|
|
629
|
+
console.log('Both tokens are supported');
|
|
438
630
|
return { valid: true };
|
|
439
631
|
} catch (error) {
|
|
632
|
+
console.log('Token validation failed:', error);
|
|
440
633
|
return { valid: false, message: 'Failed to validate tokens' };
|
|
441
634
|
}
|
|
442
635
|
};
|