1
- import { Connection , Keypair , PublicKey , Transaction , VersionedTransaction } from "@solana/web3.js" ;
1
+ import {
2
+ Connection ,
3
+ Keypair ,
4
+ PublicKey ,
5
+ Transaction ,
6
+ VersionedTransaction ,
7
+ } from "@solana/web3.js" ;
2
8
import fetch from "cross-fetch" ;
3
9
import {
4
10
ActionExample ,
@@ -7,14 +13,15 @@ import {
7
13
type Action ,
8
14
State ,
9
15
ModelClass ,
10
- HandlerCallback
16
+ HandlerCallback ,
11
17
} from "../core/types.ts" ;
12
18
import { walletProvider } from "../providers/wallet.ts" ;
13
19
import { composeContext } from "../core/context.ts" ;
14
20
import { generateObject , generateObjectArray } from "../core/generation.ts" ;
15
21
import { getTokenDecimals } from "./swapUtils.ts" ;
16
22
import settings from "../core/settings.ts" ;
17
23
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes/index.js" ;
24
+ import BigNumber from "bignumber.js" ;
18
25
19
26
async function swapToken (
20
27
connection : Connection ,
@@ -25,17 +32,25 @@ async function swapToken(
25
32
) : Promise < any > {
26
33
try {
27
34
// Get the decimals for the input token
28
- const decimals = inputTokenCA === settings . SOL_ADDRESS ? 9 :
29
- await getTokenDecimals ( connection , inputTokenCA ) ;
30
-
31
- console . log ( "Decimals:" , decimals ) ;
32
-
33
- const adjustedAmount = amount * ( 10 ** decimals ) ;
35
+ const decimals =
36
+ inputTokenCA === settings . SOL_ADDRESS
37
+ ? new BigNumber ( 9 )
38
+ : new BigNumber (
39
+ await getTokenDecimals ( connection , inputTokenCA )
40
+ ) ;
41
+
42
+ console . log ( "Decimals:" , decimals . toString ( ) ) ;
43
+
44
+ // Use BigNumber for adjustedAmount: amount * (10 ** decimals)
45
+ const amountBN = new BigNumber ( amount ) ;
46
+ const adjustedAmount = amountBN . multipliedBy (
47
+ new BigNumber ( 10 ) . pow ( decimals )
48
+ ) ;
34
49
35
50
console . log ( "Fetching quote with params:" , {
36
51
inputMint : inputTokenCA ,
37
52
outputMint : outputTokenCA ,
38
- amount : adjustedAmount
53
+ amount : adjustedAmount ,
39
54
} ) ;
40
55
41
56
const quoteResponse = await fetch (
@@ -45,7 +60,9 @@ async function swapToken(
45
60
46
61
if ( ! quoteData || quoteData . error ) {
47
62
console . error ( "Quote error:" , quoteData ) ;
48
- throw new Error ( `Failed to get quote: ${ quoteData ?. error || 'Unknown error' } ` ) ;
63
+ throw new Error (
64
+ `Failed to get quote: ${ quoteData ?. error || "Unknown error" } `
65
+ ) ;
49
66
}
50
67
51
68
console . log ( "Quote received:" , quoteData ) ;
@@ -55,7 +72,7 @@ async function swapToken(
55
72
userPublicKey : walletPublicKey . toString ( ) ,
56
73
wrapAndUnwrapSol : true ,
57
74
computeUnitPriceMicroLamports : 1000 ,
58
- dynamicComputeUnitLimit : true
75
+ dynamicComputeUnitLimit : true ,
59
76
} ;
60
77
61
78
console . log ( "Requesting swap with body:" , swapRequestBody ) ;
@@ -65,26 +82,26 @@ async function swapToken(
65
82
headers : {
66
83
"Content-Type" : "application/json" ,
67
84
} ,
68
- body : JSON . stringify ( swapRequestBody )
85
+ body : JSON . stringify ( swapRequestBody ) ,
69
86
} ) ;
70
87
71
88
const swapData = await swapResponse . json ( ) ;
72
89
73
90
if ( ! swapData || ! swapData . swapTransaction ) {
74
91
console . error ( "Swap error:" , swapData ) ;
75
- throw new Error ( `Failed to get swap transaction: ${ swapData ?. error || 'No swap transaction returned' } ` ) ;
92
+ throw new Error (
93
+ `Failed to get swap transaction: ${ swapData ?. error || "No swap transaction returned" } `
94
+ ) ;
76
95
}
77
96
78
97
console . log ( "Swap transaction received" ) ;
79
98
return swapData ;
80
-
81
99
} catch ( error ) {
82
100
console . error ( "Error in swapToken:" , error ) ;
83
101
throw error ;
84
102
}
85
103
}
86
104
87
-
88
105
const swapTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined.
89
106
90
107
Example response:
@@ -142,7 +159,6 @@ export const executeSwap: Action = {
142
159
_options : { [ key : string ] : unknown } ,
143
160
callback ?: HandlerCallback
144
161
) : Promise < boolean > => {
145
-
146
162
// composeState
147
163
if ( ! state ) {
148
164
state = ( await runtime . composeState ( message ) ) as State ;
@@ -168,10 +184,10 @@ export const executeSwap: Action = {
168
184
console . log ( "Response:" , response ) ;
169
185
170
186
// Add SOL handling logic
171
- if ( response . inputTokenSymbol ?. toUpperCase ( ) === ' SOL' ) {
187
+ if ( response . inputTokenSymbol ?. toUpperCase ( ) === " SOL" ) {
172
188
response . inputTokenCA = settings . SOL_ADDRESS ;
173
189
}
174
- if ( response . outputTokenSymbol ?. toUpperCase ( ) === ' SOL' ) {
190
+ if ( response . outputTokenSymbol ?. toUpperCase ( ) === " SOL" ) {
175
191
response . outputTokenCA = settings . SOL_ADDRESS ;
176
192
}
177
193
@@ -226,12 +242,16 @@ export const executeSwap: Action = {
226
242
) ;
227
243
228
244
console . log ( "Deserializing transaction..." ) ;
229
- const transactionBuf = Buffer . from ( swapResult . swapTransaction , "base64" ) ;
230
- const transaction = VersionedTransaction . deserialize ( transactionBuf ) ;
231
-
245
+ const transactionBuf = Buffer . from (
246
+ swapResult . swapTransaction ,
247
+ "base64"
248
+ ) ;
249
+ const transaction =
250
+ VersionedTransaction . deserialize ( transactionBuf ) ;
251
+
232
252
console . log ( "Preparing to sign transaction..." ) ;
233
253
const privateKeyString = runtime . getSetting ( "WALLET_PRIVATE_KEY" ) ;
234
-
254
+
235
255
// Handle different private key formats
236
256
let secretKey : Uint8Array ;
237
257
try {
@@ -240,25 +260,31 @@ export const executeSwap: Action = {
240
260
} catch ( e ) {
241
261
try {
242
262
// If that fails, try base64
243
- secretKey = Uint8Array . from ( Buffer . from ( privateKeyString , 'base64' ) ) ;
263
+ secretKey = Uint8Array . from (
264
+ Buffer . from ( privateKeyString , "base64" )
265
+ ) ;
244
266
} catch ( e2 ) {
245
- throw new Error ( ' Invalid private key format' ) ;
267
+ throw new Error ( " Invalid private key format" ) ;
246
268
}
247
269
}
248
270
249
271
// Verify the key length
250
272
if ( secretKey . length !== 64 ) {
251
273
console . error ( "Invalid key length:" , secretKey . length ) ;
252
- throw new Error ( `Invalid private key length: ${ secretKey . length } . Expected 64 bytes.` ) ;
274
+ throw new Error (
275
+ `Invalid private key length: ${ secretKey . length } . Expected 64 bytes.`
276
+ ) ;
253
277
}
254
278
255
279
console . log ( "Creating keypair..." ) ;
256
280
const keypair = Keypair . fromSecretKey ( secretKey ) ;
257
-
281
+
258
282
// Verify the public key matches what we expect
259
283
const expectedPublicKey = runtime . getSetting ( "WALLET_PUBLIC_KEY" ) ;
260
284
if ( keypair . publicKey . toBase58 ( ) !== expectedPublicKey ) {
261
- throw new Error ( "Generated public key doesn't match expected public key" ) ;
285
+ throw new Error (
286
+ "Generated public key doesn't match expected public key"
287
+ ) ;
262
288
}
263
289
264
290
console . log ( "Signing transaction..." ) ;
@@ -271,24 +297,31 @@ export const executeSwap: Action = {
271
297
const txid = await connection . sendTransaction ( transaction , {
272
298
skipPreflight : false ,
273
299
maxRetries : 3 ,
274
- preflightCommitment : ' confirmed'
300
+ preflightCommitment : " confirmed" ,
275
301
} ) ;
276
-
302
+
277
303
console . log ( "Transaction sent:" , txid ) ;
278
304
279
305
// Confirm transaction using the blockhash
280
- const confirmation = await connection . confirmTransaction ( {
281
- signature : txid ,
282
- blockhash : latestBlockhash . blockhash ,
283
- lastValidBlockHeight : latestBlockhash . lastValidBlockHeight
284
- } , 'confirmed' ) ;
306
+ const confirmation = await connection . confirmTransaction (
307
+ {
308
+ signature : txid ,
309
+ blockhash : latestBlockhash . blockhash ,
310
+ lastValidBlockHeight : latestBlockhash . lastValidBlockHeight ,
311
+ } ,
312
+ "confirmed"
313
+ ) ;
285
314
286
315
if ( confirmation . value . err ) {
287
- throw new Error ( `Transaction failed: ${ confirmation . value . err } ` ) ;
316
+ throw new Error (
317
+ `Transaction failed: ${ confirmation . value . err } `
318
+ ) ;
288
319
}
289
320
290
321
if ( confirmation . value . err ) {
291
- throw new Error ( `Transaction failed: ${ confirmation . value . err } ` ) ;
322
+ throw new Error (
323
+ `Transaction failed: ${ confirmation . value . err } `
324
+ ) ;
292
325
}
293
326
294
327
console . log ( "Swap completed successfully!" ) ;
@@ -299,7 +332,7 @@ export const executeSwap: Action = {
299
332
} ;
300
333
301
334
callback ?.( responseMsg ) ;
302
-
335
+
303
336
return true ;
304
337
} catch ( error ) {
305
338
console . error ( "Error during token swap:" , error ) ;
0 commit comments