@deserialize/multi-vm-wallet 1.0.0 → 1.0.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.
@@ -1,6 +1,54 @@
1
1
  import { Account } from "@solana/spl-token";
2
2
  import { Connection, Keypair, PublicKey, TransactionInstruction, VersionedTransaction } from "@solana/web3.js";
3
3
  import { TokenInfo } from "../types";
4
+ export interface JupiterQuoteResponse {
5
+ inputMint: string;
6
+ inAmount: string;
7
+ outputMint: string;
8
+ outAmount: string;
9
+ otherAmountThreshold: string;
10
+ swapMode: string;
11
+ slippageBps: number;
12
+ platformFee: null | any;
13
+ priceImpactPct: string;
14
+ routePlan: RoutePlan[];
15
+ contextSlot: number;
16
+ timeTaken: number;
17
+ }
18
+ interface RoutePlan {
19
+ swapInfo: SwapInfo;
20
+ percent: number;
21
+ }
22
+ interface SwapInfo {
23
+ ammKey: string;
24
+ label: string;
25
+ inputMint: string;
26
+ outputMint: string;
27
+ inAmount: string;
28
+ outAmount: string;
29
+ feeAmount: string;
30
+ feeMint: string;
31
+ }
32
+ interface JupiterSwapResponse {
33
+ swapTransaction: string;
34
+ lastValidBlockHeight: number;
35
+ prioritizationFeeLamports: number;
36
+ }
37
+ interface SwapParams {
38
+ fromToken: PublicKey;
39
+ toToken: PublicKey;
40
+ amount: number;
41
+ slippageBps?: number;
42
+ userPublicKey: PublicKey;
43
+ }
44
+ interface SwapResult {
45
+ success: boolean;
46
+ hash?: string;
47
+ error?: string;
48
+ inputAmount?: string;
49
+ outputAmount?: string;
50
+ priceImpact?: string;
51
+ }
4
52
  export declare const createV0Transaction: (connection: Connection, inX: TransactionInstruction[], signers: Keypair[], payerPubKey: PublicKey, blockHash?: string) => Promise<VersionedTransaction>;
5
53
  export declare const createAtaAndIx: (token: PublicKey, ownerPublicKey: PublicKey, tokenProgramId: PublicKey, connection: Connection) => Promise<{
6
54
  AtaTokenIx: any;
@@ -24,3 +72,14 @@ export declare const getTransferNativeTransaction: (from: Keypair, to: PublicKey
24
72
  export declare const getTransferTokenInx: (from: PublicKey, to: PublicKey, token: TokenInfo, amount: number, connection: Connection) => Promise<TransactionInstruction[]>;
25
73
  export declare const getTransferTokenTransaction: (from: Keypair, to: PublicKey, token: TokenInfo, amount: number, connection: Connection) => Promise<VersionedTransaction>;
26
74
  export declare const signAndSendTransaction: (transaction: VersionedTransaction, connection: Connection, signers: Keypair[]) => Promise<string>;
75
+ export declare const getJupiterQuote: (inputMint: string, outputMint: string, amount: number, slippageBps?: number) => Promise<JupiterQuoteResponse>;
76
+ export declare const buildJupiterSwapTransaction: (quote: JupiterQuoteResponse, userPublicKey: string, prioritizationFeeLamports?: number) => Promise<JupiterSwapResponse>;
77
+ export declare const executeJupiterSwap: (swapParams: SwapParams, connection: Connection, payer: Keypair) => Promise<SwapResult>;
78
+ export declare const uiAmountToBaseUnits: (uiAmount: number, decimals: number) => number;
79
+ export declare const baseUnitsToUiAmount: (baseAmount: string | number, decimals: number) => number;
80
+ export declare const getJupiterTokenList: () => Promise<any[]>;
81
+ export declare const validateJupiterTokens: (inputMint: string, outputMint: string) => Promise<{
82
+ valid: boolean;
83
+ message?: string;
84
+ }>;
85
+ export {};
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  //we will write all the svm utils function here
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.signAndSendTransaction = exports.getTransferTokenTransaction = exports.getTransferTokenInx = exports.getTransferNativeTransaction = exports.getTransferNativeInx = exports.getTokenAccountAccount = exports.getTokenBalance = exports.getSvmNativeBalance = exports.getProgramIdOfToken = exports.getSureAssociatedTokenAddressAndAccount = exports.createAtaAndIx = exports.createV0Transaction = void 0;
4
+ exports.validateJupiterTokens = exports.getJupiterTokenList = exports.baseUnitsToUiAmount = exports.uiAmountToBaseUnits = exports.executeJupiterSwap = exports.buildJupiterSwapTransaction = exports.getJupiterQuote = exports.signAndSendTransaction = exports.getTransferTokenTransaction = exports.getTransferTokenInx = exports.getTransferNativeTransaction = exports.getTransferNativeInx = exports.getTokenAccountAccount = exports.getTokenBalance = exports.getSvmNativeBalance = exports.getProgramIdOfToken = exports.getSureAssociatedTokenAddressAndAccount = exports.createAtaAndIx = exports.createV0Transaction = void 0;
5
5
  const spl_token_1 = require("@solana/spl-token");
6
6
  const web3_js_1 = require("@solana/web3.js");
7
7
  const transactionSender_1 = require("./transactionSender");
8
8
  const bn_js_1 = require("bn.js");
9
+ const JUPITER_BASE_URL = 'https://lite-api.jup.ag';
9
10
  const createV0Transaction = async (connection, inX, signers, payerPubKey, blockHash) => {
10
11
  const blockhash = blockHash || (await connection.getLatestBlockhash()).blockhash;
11
12
  const message = new web3_js_1.TransactionMessage({
@@ -71,7 +72,7 @@ const getProgramIdOfToken = async (owner, token, connection) => {
71
72
  }
72
73
  };
73
74
  exports.getProgramIdOfToken = getProgramIdOfToken;
74
- //get native balance
75
+ //get native balance
75
76
  const getSvmNativeBalance = async (address, connection) => {
76
77
  const balance = await connection.getBalance(address);
77
78
  return { balance: new bn_js_1.BN(balance), formatted: balance / web3_js_1.LAMPORTS_PER_SOL, decimal: 9 };
@@ -159,3 +160,145 @@ const signAndSendTransaction = async (transaction, connection, signers) => {
159
160
  return res.transaction.signatures[0];
160
161
  };
161
162
  exports.signAndSendTransaction = signAndSendTransaction;
163
+ //swap
164
+ //you will. use jupiter for this
165
+ const getJupiterQuote = async (inputMint, outputMint, amount, slippageBps = 50) => {
166
+ const params = new URLSearchParams({
167
+ inputMint,
168
+ outputMint,
169
+ amount: amount.toString(),
170
+ slippageBps: slippageBps.toString(),
171
+ onlyDirectRoutes: 'false',
172
+ asLegacyTransaction: 'false'
173
+ });
174
+ const response = await fetch(`${JUPITER_BASE_URL}/swap/v1/quote?${params}`);
175
+ if (!response.ok) {
176
+ const error = await response.json();
177
+ throw new Error(`Jupiter quote failed: ${error.message || response.statusText}`);
178
+ }
179
+ return await response.json();
180
+ };
181
+ exports.getJupiterQuote = getJupiterQuote;
182
+ const buildJupiterSwapTransaction = async (quote, userPublicKey, prioritizationFeeLamports) => {
183
+ const body = {
184
+ quoteResponse: quote,
185
+ userPublicKey,
186
+ wrapAndUnwrapSol: true,
187
+ useSharedAccounts: true,
188
+ feeAccount: undefined,
189
+ trackingAccount: undefined,
190
+ computeUnitPriceMicroLamports: undefined,
191
+ prioritizationFeeLamports: prioritizationFeeLamports || 1000,
192
+ asLegacyTransaction: false,
193
+ useTokenLedger: false,
194
+ destinationTokenAccount: undefined,
195
+ dynamicComputeUnitLimit: true,
196
+ skipUserAccountsRpcCalls: false
197
+ };
198
+ const response = await fetch(`${JUPITER_BASE_URL}/swap/v1/swap`, {
199
+ method: 'POST',
200
+ headers: {
201
+ 'Content-Type': 'application/json',
202
+ },
203
+ body: JSON.stringify(body),
204
+ });
205
+ if (!response.ok) {
206
+ const error = await response.json();
207
+ throw new Error(`Jupiter swap transaction build failed: ${error.message || response.statusText}`);
208
+ }
209
+ return await response.json();
210
+ };
211
+ exports.buildJupiterSwapTransaction = buildJupiterSwapTransaction;
212
+ const executeJupiterSwap = async (swapParams, connection, payer) => {
213
+ try {
214
+ console.log('Getting Jupiter quote...');
215
+ const quote = await (0, exports.getJupiterQuote)(swapParams.fromToken.toString(), swapParams.toToken.toString(), swapParams.amount, swapParams.slippageBps);
216
+ console.log('Quote received:', {
217
+ inputAmount: quote.inAmount,
218
+ outputAmount: quote.outAmount,
219
+ priceImpact: quote.priceImpactPct
220
+ });
221
+ console.log('Building swap transaction...');
222
+ const swapResponse = await (0, exports.buildJupiterSwapTransaction)(quote, swapParams.userPublicKey.toString());
223
+ console.log('Deserializing transaction...');
224
+ const swapTransactionBuf = Buffer.from(swapResponse.swapTransaction, 'base64');
225
+ const transaction = web3_js_1.VersionedTransaction.deserialize(swapTransactionBuf);
226
+ console.log('Signing transaction...');
227
+ transaction.sign([payer]);
228
+ console.log('Sending transaction...');
229
+ const blockhash = await connection.getLatestBlockhash();
230
+ const signature = await (0, transactionSender_1.transactionSenderAndConfirmationWaiter)({
231
+ connection,
232
+ serializedTransaction: Buffer.from(transaction.serialize()),
233
+ blockhashWithExpiryBlockHeight: {
234
+ blockhash: blockhash.blockhash,
235
+ lastValidBlockHeight: blockhash.lastValidBlockHeight
236
+ }
237
+ });
238
+ if (!signature) {
239
+ return {
240
+ success: false,
241
+ error: 'Transaction failed to confirm'
242
+ };
243
+ }
244
+ console.log('Swap successful! Signature:', signature.transaction.signatures[0]);
245
+ return {
246
+ success: true,
247
+ hash: signature.transaction.signatures[0],
248
+ inputAmount: quote.inAmount,
249
+ outputAmount: quote.outAmount,
250
+ priceImpact: quote.priceImpactPct
251
+ };
252
+ }
253
+ catch (error) {
254
+ console.error('Jupiter swap failed:', error);
255
+ return {
256
+ success: false,
257
+ error: error instanceof Error ? error.message : 'Unknown error occurred'
258
+ };
259
+ }
260
+ };
261
+ exports.executeJupiterSwap = executeJupiterSwap;
262
+ const uiAmountToBaseUnits = (uiAmount, decimals) => {
263
+ return Math.floor(uiAmount * Math.pow(10, decimals));
264
+ };
265
+ exports.uiAmountToBaseUnits = uiAmountToBaseUnits;
266
+ const baseUnitsToUiAmount = (baseAmount, decimals) => {
267
+ return Number(baseAmount) / Math.pow(10, decimals);
268
+ };
269
+ exports.baseUnitsToUiAmount = baseUnitsToUiAmount;
270
+ const getJupiterTokenList = async () => {
271
+ try {
272
+ const response = await fetch(`${JUPITER_BASE_URL}/tokens/v1/mints/tradable`);
273
+ if (!response.ok) {
274
+ throw new Error(`Failed to fetch token list: ${response.statusText}`);
275
+ }
276
+ return await response.json();
277
+ }
278
+ catch (error) {
279
+ console.error('Failed to fetch Jupiter token list:', error);
280
+ return [];
281
+ }
282
+ };
283
+ exports.getJupiterTokenList = getJupiterTokenList;
284
+ const validateJupiterTokens = async (inputMint, outputMint) => {
285
+ try {
286
+ const tokenList = await (0, exports.getJupiterTokenList)();
287
+ const inputSupported = tokenList.includes(inputMint);
288
+ const outputSupported = tokenList.includes(outputMint);
289
+ if (!inputSupported && !outputSupported) {
290
+ return { valid: false, message: 'Both input and output tokens are not supported' };
291
+ }
292
+ if (!inputSupported) {
293
+ return { valid: false, message: 'Input token is not supported' };
294
+ }
295
+ if (!outputSupported) {
296
+ return { valid: false, message: 'Output token is not supported' };
297
+ }
298
+ return { valid: true };
299
+ }
300
+ catch (error) {
301
+ return { valid: false, message: 'Failed to validate tokens' };
302
+ }
303
+ };
304
+ exports.validateJupiterTokens = validateJupiterTokens;
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@deserialize/multi-vm-wallet",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "devDependencies": {
5
5
  "@types/bn.js": "^5.2.0",
6
- "@types/node": "^24.1.0",
7
- "@types/promise-retry": "^1.1.6"
6
+ "@types/node": "^24.2.1",
7
+ "@types/promise-retry": "^1.1.6",
8
+ "ts-node-dev": "^2.0.0",
9
+ "typescript": "^5.9.2"
8
10
  },
9
11
  "dependencies": {
10
12
  "@solana/spl-token": "^0.4.13",
@@ -22,7 +24,8 @@
22
24
  "types": "dist/index.d.ts",
23
25
  "scripts": {
24
26
  "test": "echo \"Error: no test specified\" && exit 1",
25
- "build": "sudo rm -r dist ; tsc -p tsconfig.json",
27
+ "build": "tsc -p tsconfig.json",
28
+ "dev": "ts-node-dev --respawn --transpile-only utils/index.ts",
26
29
  "publish:sdk": "npm run build && npm publish --access=public"
27
30
  },
28
31
  "repository": {
@@ -20,6 +20,8 @@ export abstract class ChainWallet<AddressType, PrivateKeyType, ConnectionType> {
20
20
  abstract getTokenBalance(tokenAddress: AddressType): Promise<Balance>;
21
21
  abstract transferNative(to: AddressType, amount: number): Promise<TransactionResult>;
22
22
  abstract transferToken(tokenAddress: TokenInfo, to: AddressType, amount: number): Promise<TransactionResult>;
23
+ abstract swap (tokenAddress: TokenInfo, to: AddressType, amount: number, slippage?: number): Promise<TransactionResult>;
24
+
23
25
  // abstract transferNFT(contractAddress: AddressType, tokenId: string, to: string): Promise<TransactionResult>;
24
26
  // abstract getTokenInfo(tokenAddress: string): Promise<TokenInfo>;
25
27
  // abstract getNFTInfo(contractAddress: string, tokenId: string): Promise<NFTInfo>;
package/utils/evm/evm.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- *
2
+ *
3
3
  * @param phrase this is the pass phrase for this vm
4
4
  * this is a class that will be responsible for creating several evm wallets
5
5
  */
@@ -9,12 +9,24 @@ import { ChainWallet } from "../IChainWallet";
9
9
  import { Balance, ChainWalletConfig, NFTInfo, TokenInfo, TransactionResult } from "../types";
10
10
  import { VM } from "../vm";
11
11
  import { ethers, JsonRpcProvider, Wallet } from "ethers";
12
- import { getNativeBalance, getTokenBalance, sendERC20Token, sendNativeToken } from "./utils";
12
+ import BN from "bn.js";
13
+ import {
14
+ getNativeBalance,
15
+ getTokenBalance,
16
+ sendERC20Token,
17
+ sendNativeToken,
18
+ performSwap,
19
+ checkAndApprove,
20
+ signSendAndConfirm,
21
+ getNativeTokenAddress,
22
+ prepareSwapParams,
23
+ formatAmountToWei,
24
+ isChainSupportedByKyber,
25
+ TransactionParams
26
+ } from "./utils";
13
27
 
14
28
  export const createEvmVmPrivateKey = (phrase: string) => { }
15
29
 
16
-
17
-
18
30
  export class EVMVM extends VM<string, string, JsonRpcProvider> {
19
31
  derivationPath = "m/44'/60'/0'/0/"; // Default EVM derivation path
20
32
 
@@ -43,7 +55,6 @@ export class EVMVM extends VM<string, string, JsonRpcProvider> {
43
55
  }
44
56
 
45
57
  export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider> {
46
-
47
58
  constructor(config: ChainWalletConfig, privateKey: string, index: number) {
48
59
  super(config, privateKey, index);
49
60
  const wallet = new Wallet(privateKey);
@@ -51,9 +62,11 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
51
62
  this.privateKey = privateKey;
52
63
  this.connection = new JsonRpcProvider(config.rpcUrl)
53
64
  }
65
+
54
66
  getWallet(): Wallet {
55
- return new Wallet(this.privateKey);
67
+ return new Wallet(this.privateKey, this.connection);
56
68
  }
69
+
57
70
  generateAddress(): string {
58
71
  return this.address;
59
72
  }
@@ -80,5 +93,212 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
80
93
  return await sendERC20Token(wallet, tokenAddress.address, to, amount.toString(), undefined, this.config.confirmationNo || 5)
81
94
  }
82
95
 
83
- }
96
+ // Updated swap method signature to match base class so created another method to use it inside swap
97
+ async swap(
98
+ tokenAddress: TokenInfo,
99
+ to: string,
100
+ amount: number,
101
+ slippage: number = 50
102
+ ): Promise<TransactionResult> {
103
+ if (amount <= 0) {
104
+ return {
105
+ success: false,
106
+ hash: "",
107
+ error: "Amount must be greater than 0"
108
+ };
109
+ }
110
+ const tokenOut: TokenInfo = {
111
+ address: to,
112
+ name: '',
113
+ symbol: '',
114
+ decimals: 18
115
+ };
116
+
117
+ return await this.performCompleteSwap(tokenAddress, tokenOut, amount, slippage);
118
+ }
119
+
120
+ async performCompleteSwap(
121
+ tokenIn: TokenInfo,
122
+ tokenOut: TokenInfo,
123
+ amount: number,
124
+ slippage: number = 50,
125
+ recipient?: string,
126
+ deadline?: number
127
+ ): Promise<TransactionResult> {
128
+ try {
129
+ const wallet = this.getWallet();
130
+ const chainId = (await this.connection!.getNetwork()).chainId.toString();
131
+
132
+ console.log(` Starting swap on chain ${chainId}:`, {
133
+ from: tokenIn.symbol || tokenIn.address,
134
+ to: tokenOut.symbol || tokenOut.address,
135
+ amount: amount,
136
+ slippage: `${slippage / 100}%`
137
+ });
138
+
139
+ if (!isChainSupportedByKyber(chainId)) {
140
+ throw new Error(`Chain ${chainId} is not supported by KyberSwap`);
141
+ }
142
+
143
+ const isNativeIn = tokenIn.address === 'native' ||
144
+ tokenIn.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
145
+ const isNativeOut = tokenOut.address === 'native' ||
146
+ tokenOut.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
147
+
148
+ let tokenInDecimals = 18;
149
+ if (!isNativeIn && tokenIn.decimals) {
150
+ tokenInDecimals = tokenIn.decimals;
151
+ } else if (!isNativeIn) {
152
+ const tokenBalance = await this.getTokenBalance(tokenIn.address);
153
+ tokenInDecimals = tokenBalance.decimal;
154
+ }
155
+
156
+ const { tokenInAddress, tokenOutAddress, formattedAmountIn } = prepareSwapParams(
157
+ tokenIn.address,
158
+ tokenOut.address,
159
+ amount.toString(),
160
+ tokenInDecimals,
161
+ isNativeIn,
162
+ isNativeOut
163
+ );
164
+
165
+ console.log('Swap parameters:', {
166
+ tokenInAddress,
167
+ tokenOutAddress,
168
+ formattedAmountIn,
169
+ tokenInDecimals
170
+ });
171
+
172
+ if (isNativeIn) {
173
+ const nativeBalance = await this.getNativeBalance();
174
+ const requiredAmount = new BN(formattedAmountIn);
175
+ if (nativeBalance.balance.lt(requiredAmount)) {
176
+ throw new Error(`Insufficient native balance. Required: ${amount}, Available: ${nativeBalance.formatted}`);
177
+ }
178
+ } else {
179
+ const tokenBalance = await this.getTokenBalance(tokenIn.address);
180
+ const requiredAmount = new BN(formattedAmountIn);
181
+ if (tokenBalance.balance.lt(requiredAmount)) {
182
+ throw new Error(`Insufficient token balance. Required: ${amount}, Available: ${tokenBalance.formatted}`);
183
+ }
184
+ }
84
185
 
186
+ const swapTx = await performSwap({
187
+ chainId,
188
+ tokenIn: tokenInAddress,
189
+ tokenOut: tokenOutAddress,
190
+ amountIn: formattedAmountIn,
191
+ sender: this.address,
192
+ recipient: recipient || this.address,
193
+ slippageTolerance: slippage,
194
+ deadline: deadline ? Math.floor(Date.now() / 1000) + deadline : Math.floor(Date.now() / 1000) + 1200, // 20 minutes default
195
+ clientId: 'EVMChainWallet'
196
+ });
197
+
198
+ console.log('Swap transaction prepared:', {
199
+ to: swapTx.to,
200
+ dataLength: swapTx.data?.length || 0,
201
+ gasLimit: swapTx.gasLimit?.toString(),
202
+ value: swapTx.value?.toString()
203
+ });
204
+
205
+ if (!isNativeIn) {
206
+ console.log('Checking token approval...');
207
+ const approvalResult = await checkAndApprove(
208
+ wallet,
209
+ tokenIn.address,
210
+ swapTx.to,
211
+ formattedAmountIn,
212
+ undefined,
213
+ undefined,
214
+ this.config.confirmationNo || 1
215
+ );
216
+
217
+ if (approvalResult.approvalNeeded && approvalResult.approvalResult) {
218
+ if (!approvalResult.approvalResult.success) {
219
+ throw new Error('Token approval failed');
220
+ }
221
+ console.log('Token approval successful');
222
+ } else if (approvalResult.approvalNeeded) {
223
+ throw new Error('Token approval was needed but failed');
224
+ } else {
225
+ console.log('Token approval not needed - sufficient allowance');
226
+ }
227
+ }
228
+
229
+ const result = await signSendAndConfirm(
230
+ wallet,
231
+ {
232
+ to: swapTx.to,
233
+ data: swapTx.data,
234
+ value: swapTx.value || '0',
235
+ gasLimit: swapTx.gasLimit
236
+ },
237
+ this.config.confirmationNo || 1,
238
+ );
239
+
240
+ if (result.success) {
241
+ console.log(' Swap completed successfully:', {
242
+ hash: result.hash,
243
+ gasUsed: result.gasUsed?.toString(),
244
+ blockNumber: result.blockNumber
245
+ });
246
+ } else {
247
+ console.log(' Swap failed:', result);
248
+ }
249
+
250
+ return result;
251
+
252
+ } catch (error) {
253
+ console.error('Swap failed:', error);
254
+ throw new Error(`Swap failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
255
+ }
256
+ }
257
+
258
+ async getSwapQuote(
259
+ tokenIn: TokenInfo,
260
+ tokenOut: TokenInfo,
261
+ amount: number
262
+ ): Promise<{
263
+ amountOut: string;
264
+ priceImpact: string;
265
+ gasEstimate: string;
266
+ route: string[];
267
+ }> {
268
+ try {
269
+ const chainId = (await this.connection!.getNetwork()).chainId.toString();
270
+
271
+ if (!isChainSupportedByKyber(chainId)) {
272
+ throw new Error(`Chain ${chainId} is not supported by KyberSwap`);
273
+ }
274
+
275
+ const isNativeIn = tokenIn.address === 'native' ||
276
+ tokenIn.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
277
+ const isNativeOut = tokenOut.address === 'native' ||
278
+ tokenOut.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
279
+
280
+ let tokenInDecimals = 18;
281
+ if (!isNativeIn && tokenIn.decimals) {
282
+ tokenInDecimals = tokenIn.decimals;
283
+ } else if (!isNativeIn) {
284
+ const tokenBalance = await this.getTokenBalance(tokenIn.address);
285
+ tokenInDecimals = tokenBalance.decimal;
286
+ }
287
+
288
+ const { tokenInAddress, tokenOutAddress, formattedAmountIn } = prepareSwapParams(
289
+ tokenIn.address,
290
+ tokenOut.address,
291
+ amount.toString(),
292
+ tokenInDecimals,
293
+ isNativeIn,
294
+ isNativeOut
295
+ );
296
+
297
+ throw new Error("Quote functionality requires direct API integration - use the swap method for full execution");
298
+
299
+ } catch (error) {
300
+ console.error('Error getting swap quote:', error);
301
+ throw error;
302
+ }
303
+ }
304
+ }