@deserialize/multi-vm-wallet 1.0.0 → 1.0.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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  *
3
3
  * @param phrase this is the pass phrase for this vm
4
- * this is a class that will be responsible for creating several evm wallets
4
+ * this is a class that will be responsible for creating several evm wallets code
5
5
  */
6
6
  import { ChainWallet } from "../IChainWallet";
7
7
  import { Balance, ChainWalletConfig, TokenInfo, TransactionResult } from "../types";
@@ -10,11 +10,12 @@ import { JsonRpcProvider, Wallet } from "ethers";
10
10
  export declare const createEvmVmPrivateKey: (phrase: string) => void;
11
11
  export declare class EVMVM extends VM<string, string, JsonRpcProvider> {
12
12
  derivationPath: string;
13
- constructor(mnemonic: string);
14
- generatePrivateKey(index: number, seedPhrase?: string, derivationPath?: string): {
13
+ constructor(seed: string);
14
+ generatePrivateKey(index: number, seed?: string, mnemonic?: string, derivationPath?: string): {
15
15
  privateKey: string;
16
16
  index: number;
17
17
  };
18
+ static fromMnemonic(seed: string): VM<string, string, JsonRpcProvider>;
18
19
  validateAddress(address: string): boolean;
19
20
  static getNativeBalance(address: string, connection: JsonRpcProvider): Promise<Balance>;
20
21
  static getTokenBalance(address: string, tokenAddress: string, connection: JsonRpcProvider): Promise<Balance>;
@@ -27,4 +28,12 @@ export declare class EVMChainWallet extends ChainWallet<string, string, JsonRpcP
27
28
  getTokenBalance(tokenAddress: string): Promise<Balance>;
28
29
  transferNative(to: string, amount: number): Promise<TransactionResult>;
29
30
  transferToken(tokenAddress: TokenInfo, to: string, amount: number): Promise<TransactionResult>;
31
+ swap(tokenAddress: TokenInfo, to: string, amount: number, slippage?: number): Promise<TransactionResult>;
32
+ performCompleteSwap(tokenIn: TokenInfo, tokenOut: TokenInfo, amount: number, slippage?: number, recipient?: string, deadline?: number): Promise<TransactionResult>;
33
+ getSwapQuote(tokenIn: TokenInfo, tokenOut: TokenInfo, amount: number): Promise<{
34
+ amountOut: string;
35
+ priceImpact: string;
36
+ gasEstimate: string;
37
+ route: string[];
38
+ }>;
30
39
  }
@@ -2,27 +2,43 @@
2
2
  /**
3
3
  *
4
4
  * @param phrase this is the pass phrase for this vm
5
- * this is a class that will be responsible for creating several evm wallets
5
+ * this is a class that will be responsible for creating several evm wallets code
6
6
  */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
7
10
  Object.defineProperty(exports, "__esModule", { value: true });
8
11
  exports.EVMChainWallet = exports.EVMVM = exports.createEvmVmPrivateKey = void 0;
9
12
  const bip32_1 = require("../bip32");
10
13
  const IChainWallet_1 = require("../IChainWallet");
11
14
  const vm_1 = require("../vm");
12
15
  const ethers_1 = require("ethers");
16
+ const bn_js_1 = __importDefault(require("bn.js"));
13
17
  const utils_1 = require("./utils");
14
18
  const createEvmVmPrivateKey = (phrase) => { };
15
19
  exports.createEvmVmPrivateKey = createEvmVmPrivateKey;
16
20
  class EVMVM extends vm_1.VM {
17
- constructor(mnemonic) {
18
- super(mnemonic, "EVM");
21
+ constructor(seed) {
22
+ super(seed, "EVM");
19
23
  this.derivationPath = "m/44'/60'/0'/0/"; // Default EVM derivation path
20
24
  }
21
- generatePrivateKey(index, seedPhrase = this.mnemonic, derivationPath = this.derivationPath) {
22
- const seed = this.mnemonicToSeed(seedPhrase);
23
- const privateKey = (0, bip32_1.EVMDeriveChildPrivateKey)(seed, index, derivationPath).privateKey;
25
+ generatePrivateKey(index, seed, mnemonic, derivationPath = this.derivationPath) {
26
+ let _seed;
27
+ if (seed) {
28
+ _seed = seed;
29
+ }
30
+ else if (mnemonic) {
31
+ _seed = vm_1.VM.mnemonicToSeed(mnemonic);
32
+ }
33
+ else {
34
+ _seed = this.seed;
35
+ }
36
+ const privateKey = (0, bip32_1.EVMDeriveChildPrivateKey)(_seed, index, derivationPath).privateKey;
24
37
  return { privateKey, index };
25
38
  }
39
+ static fromMnemonic(seed) {
40
+ return new EVMVM(seed);
41
+ }
26
42
  validateAddress(address) {
27
43
  return ethers_1.ethers.isAddress(address);
28
44
  }
@@ -45,7 +61,7 @@ class EVMChainWallet extends IChainWallet_1.ChainWallet {
45
61
  this.connection = new ethers_1.JsonRpcProvider(config.rpcUrl);
46
62
  }
47
63
  getWallet() {
48
- return new ethers_1.Wallet(this.privateKey);
64
+ return new ethers_1.Wallet(this.privateKey, this.connection);
49
65
  }
50
66
  generateAddress() {
51
67
  return this.address;
@@ -68,5 +84,150 @@ class EVMChainWallet extends IChainWallet_1.ChainWallet {
68
84
  const wallet = this.getWallet();
69
85
  return await (0, utils_1.sendERC20Token)(wallet, tokenAddress.address, to, amount.toString(), undefined, this.config.confirmationNo || 5);
70
86
  }
87
+ // Updated swap method signature to match base class so created another method to use it inside swap
88
+ async swap(tokenAddress, to, amount, slippage = 50) {
89
+ if (amount <= 0) {
90
+ return {
91
+ success: false,
92
+ hash: "",
93
+ error: "Amount must be greater than 0"
94
+ };
95
+ }
96
+ const tokenOut = {
97
+ address: to,
98
+ name: '',
99
+ symbol: '',
100
+ decimals: 18
101
+ };
102
+ return await this.performCompleteSwap(tokenAddress, tokenOut, amount, slippage);
103
+ }
104
+ async performCompleteSwap(tokenIn, tokenOut, amount, slippage = 50, recipient, deadline) {
105
+ try {
106
+ const wallet = this.getWallet();
107
+ const chainId = (await this.connection.getNetwork()).chainId.toString();
108
+ console.log(` Starting swap on chain ${chainId}:`, {
109
+ from: tokenIn.symbol || tokenIn.address,
110
+ to: tokenOut.symbol || tokenOut.address,
111
+ amount: amount,
112
+ slippage: `${slippage / 100}%`
113
+ });
114
+ if (!(0, utils_1.isChainSupportedByKyber)(chainId)) {
115
+ throw new Error(`Chain ${chainId} is not supported by KyberSwap`);
116
+ }
117
+ const isNativeIn = tokenIn.address === 'native' ||
118
+ tokenIn.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
119
+ const isNativeOut = tokenOut.address === 'native' ||
120
+ tokenOut.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
121
+ let tokenInDecimals = 18;
122
+ if (!isNativeIn && tokenIn.decimals) {
123
+ tokenInDecimals = tokenIn.decimals;
124
+ }
125
+ else if (!isNativeIn) {
126
+ const tokenBalance = await this.getTokenBalance(tokenIn.address);
127
+ tokenInDecimals = tokenBalance.decimal;
128
+ }
129
+ const { tokenInAddress, tokenOutAddress, formattedAmountIn } = (0, utils_1.prepareSwapParams)(tokenIn.address, tokenOut.address, amount.toString(), tokenInDecimals, isNativeIn, isNativeOut);
130
+ console.log('Swap parameters:', {
131
+ tokenInAddress,
132
+ tokenOutAddress,
133
+ formattedAmountIn,
134
+ tokenInDecimals
135
+ });
136
+ if (isNativeIn) {
137
+ const nativeBalance = await this.getNativeBalance();
138
+ const requiredAmount = new bn_js_1.default(formattedAmountIn);
139
+ if (nativeBalance.balance.lt(requiredAmount)) {
140
+ throw new Error(`Insufficient native balance. Required: ${amount}, Available: ${nativeBalance.formatted}`);
141
+ }
142
+ }
143
+ else {
144
+ const tokenBalance = await this.getTokenBalance(tokenIn.address);
145
+ const requiredAmount = new bn_js_1.default(formattedAmountIn);
146
+ if (tokenBalance.balance.lt(requiredAmount)) {
147
+ throw new Error(`Insufficient token balance. Required: ${amount}, Available: ${tokenBalance.formatted}`);
148
+ }
149
+ }
150
+ const swapTx = await (0, utils_1.performSwap)({
151
+ chainId,
152
+ tokenIn: tokenInAddress,
153
+ tokenOut: tokenOutAddress,
154
+ amountIn: formattedAmountIn,
155
+ sender: this.address,
156
+ recipient: recipient || this.address,
157
+ slippageTolerance: slippage,
158
+ deadline: deadline ? Math.floor(Date.now() / 1000) + deadline : Math.floor(Date.now() / 1000) + 1200, // 20 minutes default
159
+ clientId: 'EVMChainWallet'
160
+ });
161
+ console.log('Swap transaction prepared:', {
162
+ to: swapTx.to,
163
+ dataLength: swapTx.data?.length || 0,
164
+ gasLimit: swapTx.gasLimit?.toString(),
165
+ value: swapTx.value?.toString()
166
+ });
167
+ if (!isNativeIn) {
168
+ console.log('Checking token approval...');
169
+ const approvalResult = await (0, utils_1.checkAndApprove)(wallet, tokenIn.address, swapTx.to, formattedAmountIn, undefined, undefined, this.config.confirmationNo || 1);
170
+ if (approvalResult.approvalNeeded && approvalResult.approvalResult) {
171
+ if (!approvalResult.approvalResult.success) {
172
+ throw new Error('Token approval failed');
173
+ }
174
+ console.log('Token approval successful');
175
+ }
176
+ else if (approvalResult.approvalNeeded) {
177
+ throw new Error('Token approval was needed but failed');
178
+ }
179
+ else {
180
+ console.log('Token approval not needed - sufficient allowance');
181
+ }
182
+ }
183
+ const result = await (0, utils_1.signSendAndConfirm)(wallet, {
184
+ to: swapTx.to,
185
+ data: swapTx.data,
186
+ value: swapTx.value || '0',
187
+ gasLimit: swapTx.gasLimit
188
+ }, this.config.confirmationNo || 1);
189
+ if (result.success) {
190
+ console.log(' Swap completed successfully:', {
191
+ hash: result.hash,
192
+ gasUsed: result.gasUsed?.toString(),
193
+ blockNumber: result.blockNumber
194
+ });
195
+ }
196
+ else {
197
+ console.log(' Swap failed:', result);
198
+ }
199
+ return result;
200
+ }
201
+ catch (error) {
202
+ console.error('Swap failed:', error);
203
+ throw new Error(`Swap failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
204
+ }
205
+ }
206
+ async getSwapQuote(tokenIn, tokenOut, amount) {
207
+ try {
208
+ const chainId = (await this.connection.getNetwork()).chainId.toString();
209
+ if (!(0, utils_1.isChainSupportedByKyber)(chainId)) {
210
+ throw new Error(`Chain ${chainId} is not supported by KyberSwap`);
211
+ }
212
+ const isNativeIn = tokenIn.address === 'native' ||
213
+ tokenIn.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
214
+ const isNativeOut = tokenOut.address === 'native' ||
215
+ tokenOut.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
216
+ let tokenInDecimals = 18;
217
+ if (!isNativeIn && tokenIn.decimals) {
218
+ tokenInDecimals = tokenIn.decimals;
219
+ }
220
+ else if (!isNativeIn) {
221
+ const tokenBalance = await this.getTokenBalance(tokenIn.address);
222
+ tokenInDecimals = tokenBalance.decimal;
223
+ }
224
+ const { tokenInAddress, tokenOutAddress, formattedAmountIn } = (0, utils_1.prepareSwapParams)(tokenIn.address, tokenOut.address, amount.toString(), tokenInDecimals, isNativeIn, isNativeOut);
225
+ throw new Error("Quote functionality requires direct API integration - use the swap method for full execution");
226
+ }
227
+ catch (error) {
228
+ console.error('Error getting swap quote:', error);
229
+ throw error;
230
+ }
231
+ }
71
232
  }
72
233
  exports.EVMChainWallet = EVMChainWallet;
@@ -1,6 +1,6 @@
1
1
  import { Balance } from '../types';
2
2
  import { JsonRpcProvider, Wallet, TransactionReceipt } from 'ethers';
3
- interface TransactionParams {
3
+ export interface TransactionParams {
4
4
  to: string;
5
5
  value?: string | bigint;
6
6
  data?: string;
@@ -19,6 +19,92 @@ interface TransactionResult {
19
19
  blockNumber?: number;
20
20
  confirmations: number;
21
21
  }
22
+ export interface SwapParams {
23
+ tokenIn: string;
24
+ tokenOut: string;
25
+ amountIn: string;
26
+ slippageTolerance?: number;
27
+ recipient?: string;
28
+ deadline?: number;
29
+ feeAmount?: string;
30
+ feeReceiver?: string;
31
+ isInBps?: boolean;
32
+ chargeFeeBy?: 'currency_in' | 'currency_out';
33
+ }
34
+ export interface KyberRoute {
35
+ tokenIn: string;
36
+ amountIn: string;
37
+ tokenOut: string;
38
+ amountOut: string;
39
+ gas: string;
40
+ gasPrice: string;
41
+ gasUsd: number;
42
+ amountOutUsd: string;
43
+ receivedUsd: string;
44
+ swaps: Array<{
45
+ pool: string;
46
+ tokenIn: string;
47
+ tokenOut: string;
48
+ swapAmount: string;
49
+ amountOut: string;
50
+ limitReturnAmount: string;
51
+ maxPrice: string;
52
+ exchange: string;
53
+ poolLength: number;
54
+ poolType: string;
55
+ }>;
56
+ tokens: {
57
+ [address: string]: {
58
+ address: string;
59
+ symbol: string;
60
+ name: string;
61
+ decimals: number;
62
+ price: number;
63
+ };
64
+ };
65
+ }
66
+ export interface KyberSwapResponse {
67
+ code: number;
68
+ message: string;
69
+ data: {
70
+ routeSummary: KyberRoute;
71
+ routerAddress: string;
72
+ };
73
+ }
74
+ export interface KyberBuildResponse {
75
+ code: number;
76
+ message: string;
77
+ data: {
78
+ amountIn: string;
79
+ amountInUsd: string;
80
+ amountOut: string;
81
+ amountOutUsd: string;
82
+ gas: string;
83
+ gasUsd: string;
84
+ outputChange: {
85
+ amount: string;
86
+ percent: number;
87
+ level: number;
88
+ };
89
+ data: string;
90
+ routerAddress: string;
91
+ };
92
+ }
93
+ interface KyberSwapParams {
94
+ chainId: string;
95
+ tokenIn: string;
96
+ tokenOut: string;
97
+ amountIn: string;
98
+ slippageTolerance?: number;
99
+ recipient?: string;
100
+ sender?: string;
101
+ deadline?: number;
102
+ feeAmount?: string;
103
+ feeReceiver?: string;
104
+ isInBps?: boolean;
105
+ chargeFeeBy?: 'currency_in' | 'currency_out';
106
+ clientId?: string;
107
+ }
22
108
  export declare const getNativeBalance: (address: string, provider: JsonRpcProvider) => Promise<Balance>;
23
109
  export declare const getTokenBalance: (tokenAddress: string, walletAddress: string, provider: JsonRpcProvider) => Promise<Balance>;
24
110
  /**
@@ -89,4 +175,33 @@ export declare const safeApprove: (wallet: Wallet, tokenAddress: string, spender
89
175
  resetResult: TransactionResult;
90
176
  approveResult: TransactionResult;
91
177
  }>;
178
+ export declare function getKyberSwapRoute(params: KyberSwapParams): Promise<KyberSwapResponse>;
179
+ export declare function buildKyberSwapTransaction(chainId: string, routeSummary: KyberRoute, sender: string, recipient: string, slippageTolerance?: number, deadline?: number, clientId?: string): Promise<KyberBuildResponse>;
180
+ export declare function performSwap(params: {
181
+ chainId: string;
182
+ tokenIn: string;
183
+ tokenOut: string;
184
+ amountIn: string;
185
+ sender: string;
186
+ recipient?: string;
187
+ slippageTolerance?: number;
188
+ deadline?: number;
189
+ feeAmount?: string;
190
+ feeReceiver?: string;
191
+ isInBps?: boolean;
192
+ chargeFeeBy?: 'currency_in' | 'currency_out';
193
+ clientId?: string;
194
+ }): Promise<TransactionParams>;
195
+ export declare function getKyberSupportedChains(): {
196
+ [key: string]: string;
197
+ };
198
+ export declare function isChainSupportedByKyber(chainId: string): boolean;
199
+ export declare function getNativeTokenAddress(): string;
200
+ export declare function formatAmountToWei(amount: string, decimals: number): string;
201
+ export declare function formatAmountFromWei(amountWei: string, decimals: number): string;
202
+ export declare function prepareSwapParams(tokenIn: string, tokenOut: string, amountIn: string, tokenInDecimals: number, isNativeIn?: boolean, isNativeOut?: boolean): {
203
+ tokenInAddress: string;
204
+ tokenOutAddress: string;
205
+ formattedAmountIn: string;
206
+ };
92
207
  export {};
@@ -4,8 +4,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.safeApprove = exports.resetAllowance = exports.checkAndApprove = exports.approveTokenUnlimited = exports.approveToken = exports.isAllowanceSufficient = exports.checkAllowance = exports.estimateGas = exports.getGasPrices = exports.executeContractMethod = exports.sendERC20Token = exports.sendNativeToken = exports.signSendAndConfirm = exports.getTokenBalance = exports.getNativeBalance = void 0;
7
+ exports.getKyberSwapRoute = getKyberSwapRoute;
8
+ exports.buildKyberSwapTransaction = buildKyberSwapTransaction;
9
+ exports.performSwap = performSwap;
10
+ exports.getKyberSupportedChains = getKyberSupportedChains;
11
+ exports.isChainSupportedByKyber = isChainSupportedByKyber;
12
+ exports.getNativeTokenAddress = getNativeTokenAddress;
13
+ exports.formatAmountToWei = formatAmountToWei;
14
+ exports.formatAmountFromWei = formatAmountFromWei;
15
+ exports.prepareSwapParams = prepareSwapParams;
7
16
  const ethers_1 = require("ethers");
8
17
  const bn_js_1 = __importDefault(require("bn.js"));
18
+ const KYBER_BASE_URL = 'https://aggregator-api.kyberswap.com';
19
+ const KYBER_SUPPORTED_CHAINS = {
20
+ '1': 'ethereum',
21
+ '137': 'polygon',
22
+ '56': 'bsc',
23
+ '43114': 'avalanche',
24
+ '250': 'fantom',
25
+ '42161': 'arbitrum',
26
+ '10': 'optimism',
27
+ '8453': 'base',
28
+ '324': 'zksync',
29
+ '59144': 'linea'
30
+ };
9
31
  // ERC-20 ABI
10
32
  const ERC20_ABI = [
11
33
  "function balanceOf(address owner) view returns (uint256)",
@@ -344,3 +366,172 @@ const safeApprove = async (wallet, tokenAddress, spender, amount, gasLimit, conf
344
366
  };
345
367
  exports.safeApprove = safeApprove;
346
368
  //swaps
369
+ //kyber swap here
370
+ //docs -. https://docs.kyberswap.com/kyberswap-solutions/kyberswap-aggregator/developer-guides/execute-a-swap-with-the-aggregator-api
371
+ // the major constrain is that each function should return a transaction to sign, do not sign transaction or send transaction within util functions
372
+ // let the ChainWalletClass be the one to sign and send,
373
+ //so in you chainWallet.swap, you can have the futil swap function to get the transaction then another function to sign and send and confirm the transaction
374
+ async function getKyberSwapRoute(params) {
375
+ const chainName = KYBER_SUPPORTED_CHAINS[params.chainId];
376
+ if (!chainName) {
377
+ throw new Error(`Unsupported chain ID: ${params.chainId}`);
378
+ }
379
+ const queryParams = new URLSearchParams({
380
+ tokenIn: params.tokenIn,
381
+ tokenOut: params.tokenOut,
382
+ amountIn: params.amountIn,
383
+ });
384
+ if (params.feeAmount)
385
+ queryParams.append('feeAmount', params.feeAmount);
386
+ if (params.feeReceiver)
387
+ queryParams.append('feeReceiver', params.feeReceiver);
388
+ if (params.isInBps !== undefined)
389
+ queryParams.append('isInBps', params.isInBps.toString());
390
+ if (params.chargeFeeBy)
391
+ queryParams.append('chargeFeeBy', params.chargeFeeBy);
392
+ const url = `${KYBER_BASE_URL}/${chainName}/api/v1/routes?${queryParams}`;
393
+ const headers = {};
394
+ if (params.clientId) {
395
+ headers['x-client-id'] = params.clientId;
396
+ }
397
+ try {
398
+ const response = await fetch(url, { headers });
399
+ const data = await response.json();
400
+ if (!response.ok) {
401
+ throw new Error(`KyberSwap API error: ${data.message || response.statusText}`);
402
+ }
403
+ return data;
404
+ }
405
+ catch (error) {
406
+ console.error('Error fetching KyberSwap route:', error);
407
+ throw error;
408
+ }
409
+ }
410
+ async function buildKyberSwapTransaction(chainId, routeSummary, sender, recipient, slippageTolerance = 50, deadline, clientId) {
411
+ const chainName = KYBER_SUPPORTED_CHAINS[chainId];
412
+ if (!chainName) {
413
+ throw new Error(`Unsupported chain ID: ${chainId}`);
414
+ }
415
+ const url = `${KYBER_BASE_URL}/${chainName}/api/v1/route/build`;
416
+ const txDeadline = deadline || Math.floor(Date.now() / 1000) + 1200;
417
+ const body = {
418
+ routeSummary,
419
+ sender,
420
+ recipient,
421
+ slippageTolerance,
422
+ deadline: txDeadline,
423
+ source: clientId || 'MyWalletApp'
424
+ };
425
+ const headers = {
426
+ 'Content-Type': 'application/json',
427
+ };
428
+ if (clientId) {
429
+ headers['x-client-id'] = clientId;
430
+ }
431
+ try {
432
+ const response = await fetch(url, {
433
+ method: 'POST',
434
+ headers,
435
+ body: JSON.stringify(body)
436
+ });
437
+ const data = await response.json();
438
+ if (!response.ok) {
439
+ throw new Error(`KyberSwap build API error: ${data.message || response.statusText}`);
440
+ }
441
+ return data;
442
+ }
443
+ catch (error) {
444
+ console.error('Error building KyberSwap transaction:', error);
445
+ throw error;
446
+ }
447
+ }
448
+ async function performSwap(params) {
449
+ try {
450
+ console.log('Starting KyberSwap aggregation...', {
451
+ tokenIn: params.tokenIn,
452
+ tokenOut: params.tokenOut,
453
+ amountIn: params.amountIn,
454
+ chainId: params.chainId
455
+ });
456
+ console.log('Fetching best swap route across all DEXs...');
457
+ const routeResponse = await getKyberSwapRoute({
458
+ chainId: params.chainId,
459
+ tokenIn: params.tokenIn,
460
+ tokenOut: params.tokenOut,
461
+ amountIn: params.amountIn,
462
+ feeAmount: params.feeAmount,
463
+ feeReceiver: params.feeReceiver,
464
+ isInBps: params.isInBps,
465
+ chargeFeeBy: params.chargeFeeBy,
466
+ clientId: params.clientId || 'MyWalletApp'
467
+ });
468
+ if (!routeResponse.data || !routeResponse.data.routeSummary) {
469
+ throw new Error('No valid route found for the swap');
470
+ }
471
+ const { routeSummary, routerAddress } = routeResponse.data;
472
+ console.log('✅ Best route found:', {
473
+ tokenIn: routeSummary.tokenIn,
474
+ tokenOut: routeSummary.tokenOut,
475
+ amountIn: routeSummary.amountIn,
476
+ amountOut: routeSummary.amountOut,
477
+ gasEstimate: routeSummary.gas,
478
+ routerAddress,
479
+ dexSources: routeSummary.swaps.map(swap => swap.exchange)
480
+ });
481
+ console.log(' Building executable transaction...');
482
+ const buildResponse = await buildKyberSwapTransaction(params.chainId, routeSummary, params.sender, params.recipient || params.sender, params.slippageTolerance || 50, params.deadline, params.clientId || 'MyWalletApp');
483
+ if (!buildResponse.data || !buildResponse.data.data) {
484
+ throw new Error('Failed to build transaction data');
485
+ }
486
+ const { data: encodedData, gas, routerAddress: finalRouterAddress } = buildResponse.data;
487
+ console.log('✅ Transaction built successfully:', {
488
+ to: finalRouterAddress,
489
+ dataLength: encodedData.length,
490
+ gasEstimate: gas,
491
+ expectedOutput: buildResponse.data.amountOut
492
+ });
493
+ return {
494
+ to: finalRouterAddress,
495
+ data: encodedData,
496
+ gasLimit: gas,
497
+ value: params.tokenIn.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
498
+ ? params.amountIn
499
+ : '0'
500
+ };
501
+ }
502
+ catch (error) {
503
+ console.error('❌ KyberSwap aggregation failed:', error);
504
+ throw new Error(`Swap preparation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
505
+ }
506
+ }
507
+ function getKyberSupportedChains() {
508
+ return { ...KYBER_SUPPORTED_CHAINS };
509
+ }
510
+ function isChainSupportedByKyber(chainId) {
511
+ return chainId in KYBER_SUPPORTED_CHAINS;
512
+ }
513
+ function getNativeTokenAddress() {
514
+ return '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
515
+ }
516
+ function formatAmountToWei(amount, decimals) {
517
+ const amountBN = new bn_js_1.default(amount);
518
+ const multiplier = new bn_js_1.default(10).pow(new bn_js_1.default(decimals));
519
+ return amountBN.mul(multiplier).toString();
520
+ }
521
+ function formatAmountFromWei(amountWei, decimals) {
522
+ const amountBN = new bn_js_1.default(amountWei);
523
+ const divisor = new bn_js_1.default(10).pow(new bn_js_1.default(decimals));
524
+ return amountBN.div(divisor).toString();
525
+ }
526
+ function prepareSwapParams(tokenIn, tokenOut, amountIn, tokenInDecimals, isNativeIn = false, isNativeOut = false) {
527
+ const tokenInAddress = isNativeIn ? getNativeTokenAddress() : tokenIn;
528
+ const tokenOutAddress = isNativeOut ? getNativeTokenAddress() : tokenOut;
529
+ const formattedAmountIn = amountIn.includes('.')
530
+ ? formatAmountToWei(amountIn, tokenInDecimals)
531
+ : amountIn;
532
+ return {
533
+ tokenInAddress,
534
+ tokenOutAddress,
535
+ formattedAmountIn
536
+ };
537
+ }
@@ -4,3 +4,4 @@ export * from "./types";
4
4
  export * from "./vm";
5
5
  export * from "./evm";
6
6
  export * from "./svm";
7
+ export * from "./types";
@@ -20,3 +20,4 @@ __exportStar(require("./types"), exports);
20
20
  __exportStar(require("./vm"), exports);
21
21
  __exportStar(require("./evm"), exports);
22
22
  __exportStar(require("./svm"), exports);
23
+ __exportStar(require("./types"), exports);
@@ -2,17 +2,19 @@ import { Connection, Keypair, PublicKey } from "@solana/web3.js";
2
2
  import { VM } from "../vm";
3
3
  import { ChainWallet } from "../IChainWallet";
4
4
  import { Balance, ChainWalletConfig, TokenInfo, TransactionResult } from "../types";
5
+ import { JupiterQuoteResponse } from "./utils";
5
6
  export declare class SVMVM extends VM<PublicKey, Keypair, Connection> {
6
7
  derivationPath: string;
7
- constructor(mnemonic: string);
8
+ constructor(seed: string);
8
9
  static validateAddress(address: PublicKey): boolean;
9
10
  static getNativeBalance(address: PublicKey, connection: Connection): Promise<Balance>;
10
11
  static getTokenBalance(address: PublicKey, tokenAddress: PublicKey, connection: Connection): Promise<Balance>;
11
12
  static signAndSendTransaction: (transaction: import("@solana/web3.js").VersionedTransaction, connection: Connection, signers: Keypair[]) => Promise<string>;
12
- generatePrivateKey(index: number, seedPhrase?: string, derivationPath?: string): {
13
+ generatePrivateKey(index: number, seed?: string, mnemonic?: string, derivationPath?: string): {
13
14
  privateKey: Keypair;
14
15
  index: number;
15
16
  };
17
+ static fromMnemonic(seed: string): VM<PublicKey, Keypair, Connection>;
16
18
  }
17
19
  export declare class SVMChainWallet extends ChainWallet<PublicKey, Keypair, Connection> {
18
20
  constructor(config: ChainWalletConfig, privateKey: Keypair, index: number);
@@ -21,4 +23,14 @@ export declare class SVMChainWallet extends ChainWallet<PublicKey, Keypair, Conn
21
23
  getTokenBalance(tokenAddress: PublicKey): Promise<Balance>;
22
24
  transferNative(to: PublicKey, amount: number): Promise<TransactionResult>;
23
25
  transferToken(token: TokenInfo, to: PublicKey, amount: number): Promise<TransactionResult>;
26
+ swap(fromToken: TokenInfo, toToken: PublicKey, amount: number, slippage?: number): Promise<TransactionResult>;
27
+ getSwapQuote(fromToken: TokenInfo, toToken: PublicKey, amount: number, slippage?: number): Promise<{
28
+ success: boolean;
29
+ inputAmount?: string;
30
+ outputAmount?: string;
31
+ priceImpact?: string;
32
+ routePlan?: JupiterQuoteResponse['routePlan'];
33
+ slippageBps?: number;
34
+ error?: string;
35
+ }>;
24
36
  }