@deserialize/multi-vm-wallet 1.1.3 → 1.1.5

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/utils/evm/evm.ts CHANGED
@@ -8,7 +8,7 @@ import { EVMDeriveChildPrivateKey } from "../bip32";
8
8
  import { ChainWallet } from "../IChainWallet";
9
9
  import { Balance, ChainWalletConfig, NFTInfo, TokenInfo, TransactionResult } from "../types";
10
10
  import { VM } from "../vm";
11
- import { ethers, JsonRpcProvider, Wallet } from "ethers";
11
+ import { ethers, JsonRpcProvider, Wallet, formatUnits } from "ethers";
12
12
  import BN from "bn.js";
13
13
  import {
14
14
  getNativeBalance,
@@ -22,13 +22,51 @@ import {
22
22
  prepareSwapParams,
23
23
  formatAmountToWei,
24
24
  isChainSupportedByKyber,
25
+ isChainSupportedByDebonk,
26
+ // normalizeTokenAddressForDebonk,
27
+ convertSlippageForDebonk,
25
28
  TransactionParams,
26
29
  approveToken,
27
30
  executeContractMethod,
28
- getTokenInfo
31
+ getTokenInfo,
32
+ DESERIALIZED_SUPPORTED_CHAINS
29
33
  } from "./utils";
30
34
 
31
- export const createEvmVmPrivateKey = (phrase: string) => { }
35
+ interface DebonkQuoteResponse {
36
+ tokenA: string;
37
+ tokenB: string;
38
+ amountIn: string;
39
+ amountOut: string;
40
+ tokenPrice: string;
41
+ routePlan: Array<{
42
+ tokenA: string;
43
+ tokenB: string;
44
+ dexId: string;
45
+ poolAddress: string;
46
+ aToB: boolean;
47
+ fee: number;
48
+ }>;
49
+ dexId: string;
50
+ dexFactory: string;
51
+ }
52
+
53
+ interface DebonkSwapResponse {
54
+ transactions: Array<{
55
+ from: string;
56
+ to: string;
57
+ data: string;
58
+ value: string;
59
+ gasLimit?: string;
60
+ gasPrice?: string;
61
+ }>;
62
+ }
63
+
64
+ interface DebonkSwapResult {
65
+ success: boolean;
66
+ hash: string;
67
+ error?: string;
68
+ }
69
+
32
70
 
33
71
  export class EVMVM extends VM<string, string, JsonRpcProvider> {
34
72
  derivationPath = "m/44'/60'/0'/0/"; // Default EVM derivation path
@@ -153,6 +191,200 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
153
191
  slippage: `${slippage / 100}%`
154
192
  });
155
193
 
194
+ // Check if this is a 0G chain that should use Debonk
195
+ if (isChainSupportedByDebonk(chainId)) {
196
+ console.log('Using Debonk API for 0G chain swap');
197
+ return await this.performDebonkSwap(tokenIn, tokenOut, amount, slippage, recipient, deadline);
198
+ }
199
+
200
+ // Otherwise use Kyber (existing flow)
201
+ console.log('Using KyberSwap for non-0G chain swap');
202
+ return await this.performKyberSwap(tokenIn, tokenOut, amount, slippage, recipient, deadline);
203
+
204
+ } catch (error) {
205
+ console.error('Swap failed:', error);
206
+ throw new Error(`Swap failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
207
+ }
208
+ }
209
+
210
+ private async performDebonkSwap(
211
+ tokenIn: TokenInfo,
212
+ tokenOut: TokenInfo,
213
+ amount: number,
214
+ slippage: number = 50, // bps (e.g., 50 = 0.5%)
215
+ recipient?: string,
216
+ deadline?: number
217
+ ): Promise<DebonkSwapResult> {
218
+ try {
219
+ const BASE_URL = 'https://evm-api.deserialize.xyz';
220
+ const tokenInAddress = tokenIn.address;
221
+ const tokenOutAddress = tokenOut.address;
222
+
223
+ // Convert amount to wei (multiply by 10^18 for 18 decimal tokens)
224
+ const amountInWei = (amount * Math.pow(10, tokenIn.decimals || 18)).toString();
225
+ console.log("amountInWei", amountInWei)
226
+ // Convert slippage from bps to percentage (e.g., 50 bps -> 0.5%)
227
+ const slippagePercentage = slippage / 100;
228
+
229
+ console.log("Debonk API swap params:", {
230
+ tokenA: tokenInAddress,
231
+ tokenB: tokenOutAddress,
232
+ amountIn: amount,
233
+ amountInWei: amountInWei,
234
+ slippage: slippagePercentage,
235
+ });
236
+
237
+ // Step 1: Get quote from API
238
+ console.log("Getting quote from Debonk API...");
239
+
240
+ const quotePayload = {
241
+ tokenA: tokenInAddress,
242
+ tokenB: tokenOutAddress,
243
+ amountIn: amountInWei, // Use wei amount
244
+ dexId: "ZERO_G"
245
+ };
246
+
247
+ console.log("Quote request payload:", quotePayload);
248
+
249
+ const quoteResponse = await fetch(`${BASE_URL}/quote`, {
250
+ method: 'POST',
251
+ headers: {
252
+ 'Content-Type': 'application/json',
253
+ },
254
+ body: JSON.stringify(quotePayload)
255
+ });
256
+
257
+ if (!quoteResponse.ok) {
258
+ const errorText = await quoteResponse.text();
259
+ console.error("Quote API error response:", errorText);
260
+ return this.fail(`Quote API failed: ${quoteResponse.status} ${errorText}`);
261
+ }
262
+
263
+ const quote: DebonkQuoteResponse = await quoteResponse.json();
264
+ console.log("Quote received:", JSON.stringify(quote, null, 2));
265
+
266
+ // Step 2: Fix the quote dexId for swap API (it expects "ALL")
267
+ const modifiedQuote = {
268
+ ...quote,
269
+ dexId: "ALL" // Change from "ZERO_G" to "ALL" as required by swap API
270
+ };
271
+
272
+ console.log("Modified quote for swap API:", JSON.stringify(modifiedQuote, null, 2));
273
+
274
+ // Step 3: Get wallet address
275
+ const walletAddress = await this.getWallet().getAddress();
276
+ console.log("Wallet address:", walletAddress);
277
+
278
+ // Step 4: Call swap API with modified quote
279
+ console.log("Calling swap API...");
280
+
281
+ const swapPayload = {
282
+ publicKey: walletAddress,
283
+ slippage: slippagePercentage,
284
+ quote: modifiedQuote
285
+ };
286
+
287
+ console.log("Swap request payload:", JSON.stringify(swapPayload, null, 2));
288
+
289
+ const swapResponse = await fetch(`${BASE_URL}/swap`, {
290
+ method: 'POST',
291
+ headers: {
292
+ 'Content-Type': 'application/json',
293
+ },
294
+ body: JSON.stringify(swapPayload)
295
+ });
296
+
297
+ if (!swapResponse.ok) {
298
+ const errorText = await swapResponse.text();
299
+ console.error("Swap API error response:", errorText);
300
+ return this.fail(`Swap API failed: ${swapResponse.status} ${errorText}`);
301
+ }
302
+
303
+ const swapData: DebonkSwapResponse = await swapResponse.json();
304
+ console.log("Swap API response:", JSON.stringify(swapData, null, 2));
305
+
306
+ const wallet = this.getWallet();
307
+ let lastTxHash = '';
308
+
309
+ // Step 5: Execute each transaction sequentially
310
+ console.log(`Executing ${swapData.transactions.length} transactions...`);
311
+
312
+ for (let i = 0; i < swapData.transactions.length; i++) {
313
+ const transaction = swapData.transactions[i];
314
+ console.log(`Executing transaction ${i + 1} of ${swapData.transactions.length}`);
315
+
316
+ // Prepare transaction object
317
+ const txRequest = {
318
+ to: transaction.to,
319
+ data: transaction.data,
320
+ value: transaction.value,
321
+ // gasPrice: 70000000000,
322
+ // gasLimit: 70000, // Increase significantly
323
+ };
324
+ console.log("Prepared transaction request:", txRequest);
325
+ console.log(`Transaction ${i + 1} request:`, txRequest);
326
+
327
+ try {
328
+ const txResponse = await wallet.sendTransaction(txRequest);
329
+ console.log(`Transaction ${i + 1} sent:`, txResponse.hash);
330
+
331
+ // Wait for confirmation
332
+ const receipt = await txResponse.wait();
333
+
334
+ if (!receipt) {
335
+ return this.fail(`Transaction ${i + 1} failed - no receipt received`);
336
+ }
337
+
338
+ const txHash = receipt.hash || txResponse.hash;
339
+ lastTxHash = txHash;
340
+
341
+ console.log(`Transaction ${i + 1} confirmed:`, {
342
+ hash: txHash,
343
+ blockNumber: receipt.blockNumber,
344
+ gasUsed: receipt.gasUsed?.toString()
345
+ });
346
+
347
+ } catch (txError: any) {
348
+ console.error(`Transaction ${i + 1} failed:`, txError);
349
+ return this.fail(`Transaction ${i + 1} failed: ${txError?.message ?? String(txError)}`);
350
+ }
351
+ }
352
+
353
+ console.log("All transactions completed successfully");
354
+
355
+ return {
356
+ success: true,
357
+ hash: lastTxHash // Return the hash of the last transaction
358
+ };
359
+
360
+ } catch (error: any) {
361
+ console.error("Debonk API swap error:", error);
362
+ return this.fail(`Debonk API swap failed: ${error?.message ?? String(error)}`);
363
+ }
364
+ }
365
+
366
+ // Helper method for EVMChainWallet class
367
+ private fail(message: string): DebonkSwapResult {
368
+ return {
369
+ success: false,
370
+ hash: "",
371
+ error: message
372
+ };
373
+ }
374
+
375
+
376
+ private async performKyberSwap(
377
+ tokenIn: TokenInfo,
378
+ tokenOut: TokenInfo,
379
+ amount: number,
380
+ slippage: number = 50,
381
+ recipient?: string,
382
+ deadline?: number
383
+ ): Promise<TransactionResult> {
384
+ try {
385
+ const wallet = this.getWallet();
386
+ const chainId = (await this.connection!.getNetwork()).chainId.toString();
387
+
156
388
  if (!isChainSupportedByKyber(chainId)) {
157
389
  throw new Error(`Chain ${chainId} is not supported by KyberSwap`);
158
390
  }
@@ -179,7 +411,7 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
179
411
  isNativeOut
180
412
  );
181
413
 
182
- console.log('Swap parameters:', {
414
+ console.log('Kyber swap parameters:', {
183
415
  tokenInAddress,
184
416
  tokenOutAddress,
185
417
  formattedAmountIn,
@@ -212,7 +444,7 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
212
444
  clientId: 'EVMChainWallet'
213
445
  });
214
446
 
215
- console.log('Swap transaction prepared:', {
447
+ console.log('Kyber swap transaction prepared:', {
216
448
  to: swapTx.to,
217
449
  dataLength: swapTx.data?.length || 0,
218
450
  gasLimit: swapTx.gasLimit?.toString(),
@@ -255,20 +487,20 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
255
487
  );
256
488
 
257
489
  if (result.success) {
258
- console.log(' Swap completed successfully:', {
490
+ console.log(' Kyber swap completed successfully:', {
259
491
  hash: result.hash,
260
492
  gasUsed: result.gasUsed?.toString(),
261
493
  blockNumber: result.blockNumber
262
494
  });
263
495
  } else {
264
- console.log(' Swap failed:', result);
496
+ console.log(' Kyber swap failed:', result);
265
497
  }
266
498
 
267
499
  return result;
268
500
 
269
501
  } catch (error) {
270
- console.error('Swap failed:', error);
271
- throw new Error(`Swap failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
502
+ console.error('Kyber swap failed:', error);
503
+ throw new Error(`Kyber swap failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
272
504
  }
273
505
  }
274
506
 
@@ -282,6 +514,7 @@ export class EVMChainWallet extends ChainWallet<string, string, JsonRpcProvider>
282
514
  gasEstimate: string;
283
515
  route: string[];
284
516
  }> {
517
+
285
518
  try {
286
519
  const chainId = (await this.connection!.getNetwork()).chainId.toString();
287
520
 
@@ -0,0 +1,160 @@
1
+
2
+
3
+ import { ethers } from 'ethers';
4
+
5
+ // Simplified ABI for Uniswap V3 Router
6
+ const ROUTER_ABI = [
7
+ 'function exactInputSingle((address tokenIn, address tokenIn, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96)) external payable returns (uint256 amountOut)',
8
+ 'function exactOutputSingle((address tokenIn, address tokenIn, uint24 fee, address recipient, uint256 deadline, uint256 amountOut, uint256 amountInMaximum, uint160 sqrtPriceLimitX96)) external payable returns (uint256 amountIn)'
9
+ ];
10
+
11
+ // ERC20 ABI (simplified)
12
+ const ERC20_ABI = [
13
+ 'function approve(address spender, uint256 amount) external returns (bool)',
14
+ 'function allowance(address owner, address spender) external view returns (uint256)',
15
+ 'function balanceOf(address account) external view returns (uint256)'
16
+ ];
17
+
18
+ export interface SwapParams {
19
+ privateKey: string;
20
+ tokenIn: string;
21
+ tokenOut: string;
22
+ tokenInDecimal:number;
23
+ amountIn: string;
24
+ adminAddress: string;
25
+ routerAddress: string;
26
+ minAmountOut:string;
27
+ rpcUrl: string;
28
+ feeTier?: number; // 500 = 0.05%, 3000 = 0.3%, 10000 = 1%
29
+ }
30
+
31
+ export const quote = async (quoterAddress:string,rpc:string,tokenIn:string, tokenOut:string, amountIn:string, fee:number,sqrtPriceLimitX96="0") => {
32
+ const provider = new ethers.JsonRpcProvider(rpc);
33
+
34
+ const viewABI = [
35
+ {
36
+ inputs: [
37
+ { internalType: "address", name: "tokenIn", type: "address" },
38
+ { internalType: "address", name: "tokenOut", type: "address" },
39
+ { internalType: "uint24", name: "fee", type: "uint24" },
40
+ { internalType: "uint256", name: "amountIn", type: "uint256" },
41
+ { internalType: "uint160", name: "sqrtPriceLimitX96", type: "uint160" },
42
+ ],
43
+ name: "quoteExactInputSingle",
44
+ outputs: [{ internalType: "uint256", name: "amountOut", type: "uint256" }],
45
+ stateMutability: "view",
46
+ type: "function",
47
+ },
48
+ ];
49
+
50
+ const quoter = new ethers.Contract(quoterAddress, viewABI, provider);
51
+
52
+ try {
53
+ const amountOut = await quoter.quoteExactInputSingle(
54
+ tokenIn,
55
+ tokenOut,
56
+ fee,
57
+ amountIn,
58
+ sqrtPriceLimitX96
59
+ );
60
+
61
+ console.log("Amount Out:", amountOut.toString());
62
+ return amountOut.toString();
63
+ } catch (err:any) {
64
+ console.error("Quote failed:", err);
65
+ }
66
+ };
67
+
68
+
69
+ export const quickSwapSetup = async (params: SwapParams) => {
70
+ const {
71
+ privateKey,
72
+ tokenIn,
73
+ tokenOut,
74
+ amountIn,
75
+ tokenInDecimal,
76
+ adminAddress,
77
+ routerAddress,
78
+ rpcUrl,
79
+ minAmountOut,
80
+
81
+ feeTier = 100 // 0.01% fee tier
82
+ } = params;
83
+
84
+ try {
85
+ // Setup provider and wallet
86
+ const provider = new ethers.JsonRpcProvider(rpcUrl);
87
+ const wallet = new ethers.Wallet(privateKey, provider);
88
+
89
+ // Create contract instances
90
+ const router = new ethers.Contract(routerAddress, ROUTER_ABI, wallet);
91
+ const tokenInContract = new ethers.Contract(tokenIn, ERC20_ABI, wallet);
92
+
93
+ // Convert amount to wei
94
+ const amountInWei = ethers.parseUnits(amountIn, tokenInDecimal); // Assuming 18 decimals
95
+
96
+ // Check and approve token allowance
97
+ const allowance = await tokenInContract.allowance(wallet.address, routerAddress);
98
+
99
+ if (allowance < amountInWei) {
100
+ console.log('Approving tokens...');
101
+ const approveTx = await tokenInContract.approve(routerAddress, amountInWei);
102
+ await approveTx.wait();
103
+ console.log('Approval confirmed');
104
+ }
105
+
106
+ // Calculate amount with fee (0.01% to admin)
107
+ const feeAmount = amountInWei * BigInt(1) / BigInt(10000); // 0.01%
108
+ const amountAfterFee = amountInWei - feeAmount;
109
+
110
+ // Transfer fee to admin
111
+ if (feeAmount > 0) {
112
+ console.log(`Transferring ${ethers.formatUnits(feeAmount, tokenIn)} fee to admin`);
113
+ const feeTransferTx = await tokenInContract.transfer(adminAddress, feeAmount);
114
+ await feeTransferTx.wait();
115
+ }
116
+
117
+ // Set deadline (10 minutes from now)
118
+ const deadline = Math.floor(Date.now() / 1000) + 600;
119
+
120
+ // Prepare swap parameters
121
+ const swapParams = {
122
+ tokenIn: tokenIn,
123
+ tokenOut: tokenOut,
124
+ fee: feeTier,
125
+ recipient: wallet.address,
126
+ deadline: deadline,
127
+ amountIn: amountAfterFee,
128
+ amountOutMinimum: minAmountOut,
129
+ sqrtPriceLimitX96: 0
130
+ };
131
+
132
+ console.log('Executing swap...');
133
+
134
+ // Execute swap
135
+ const swapTx = await router.exactInputSingle(swapParams);
136
+ const receipt = await swapTx.wait();
137
+
138
+ console.log('Swap successful!');
139
+ console.log('Transaction hash:', receipt.hash);
140
+
141
+ // Check final balances
142
+ const tokenOutContract = new ethers.Contract(tokenOut, ERC20_ABI, wallet);
143
+ const finalBalance = await tokenOutContract.balanceOf(wallet.address);
144
+
145
+ console.log(`Final ${tokenOut} balance:`, ethers.formatUnits(finalBalance, 18));
146
+
147
+ return {
148
+ success: true,
149
+ txHash: receipt.hash,
150
+ amountOut: finalBalance.toString()
151
+ };
152
+
153
+ } catch (error) {
154
+ console.error('Swap failed:', error);
155
+ return {
156
+ success: false,
157
+ error: error instanceof Error ? error.message : 'Unknown error'
158
+ };
159
+ }
160
+ };
@@ -1,4 +1,3 @@
1
-
2
1
  import { Balance, TokenInfo } from '../types'
3
2
  import { JsonRpcProvider, Contract, Wallet, TransactionRequest, TransactionResponse, TransactionReceipt } from 'ethers'
4
3
  import BN from 'bn.js'
@@ -24,6 +23,7 @@ interface TransactionResult {
24
23
  effectiveGasPrice?: bigint
25
24
  blockNumber?: number
26
25
  confirmations: number
26
+
27
27
  }
28
28
 
29
29
  export interface SwapParams {
@@ -114,6 +114,10 @@ const KYBER_SUPPORTED_CHAINS: { [key: string]: string } = {
114
114
  '59144': 'linea'
115
115
  };
116
116
 
117
+ export const DESERIALIZED_SUPPORTED_CHAINS: { [key: string]: string } = {
118
+ '16661': '0gMainnet',
119
+ };
120
+
117
121
  interface KyberSwapParams {
118
122
  chainId: string;
119
123
  tokenIn: string;
@@ -143,13 +147,18 @@ const ERC20_ABI = [
143
147
  ]
144
148
 
145
149
  export const getNativeBalance = async (address: string, provider: JsonRpcProvider): Promise<Balance> => {
146
- const balance = await provider.getBalance(address)
150
+ const balance = await provider.getBalance(address); // returns BigInt in ethers v6
151
+
152
+ const dem = 10n ** 18n;
153
+
154
+ // ⚠️ BigInt division truncates, so avoid dividing BigInt directly
155
+ const formatted = Number(balance) / Number(dem);
147
156
 
148
157
  return {
149
- balance: new BN(balance),
150
- formatted: Number(balance / 10n ** 18n),
158
+ balance: new BN(balance.toString()), // raw wei as BN
159
+ formatted, // e.g. 0.1
151
160
  decimal: 18
152
- }
161
+ };
153
162
  }
154
163
 
155
164
  export const getTokenInfo = async (
@@ -755,6 +764,9 @@ export async function performSwap(params: {
755
764
  chargeFeeBy?: 'currency_in' | 'currency_out';
756
765
  clientId?: string;
757
766
  }): Promise<TransactionParams> {
767
+ if (!KYBER_SUPPORTED_CHAINS[params.chainId]) {
768
+ throw new Error(`KyberSwap does not support chain ID: ${params.chainId}`);
769
+ }
758
770
  try {
759
771
  console.log('Starting KyberSwap aggregation...', {
760
772
  tokenIn: params.tokenIn,
@@ -762,7 +774,9 @@ export async function performSwap(params: {
762
774
  amountIn: params.amountIn,
763
775
  chainId: params.chainId
764
776
  });
777
+
765
778
  console.log('Fetching best swap route across all DEXs...');
779
+
766
780
  const routeResponse = await getKyberSwapRoute({
767
781
  chainId: params.chainId,
768
782
  tokenIn: params.tokenIn,
@@ -775,12 +789,20 @@ export async function performSwap(params: {
775
789
  clientId: params.clientId || 'MyWalletApp'
776
790
  });
777
791
 
792
+ // Debug: Log the full response to understand structure
793
+ console.log('Full KyberSwap route response:', JSON.stringify(routeResponse, null, 2));
794
+
778
795
  if (!routeResponse.data || !routeResponse.data.routeSummary) {
779
796
  throw new Error('No valid route found for the swap');
780
797
  }
781
798
 
782
799
  const { routeSummary, routerAddress } = routeResponse.data;
783
800
 
801
+ // Debug: Log what we actually received
802
+ console.log('routeSummary keys:', Object.keys(routeSummary));
803
+ console.log('routeSummary.swaps exists:', !!routeSummary.swaps);
804
+
805
+ // Safe logging that handles undefined swaps
784
806
  console.log('✅ Best route found:', {
785
807
  tokenIn: routeSummary.tokenIn,
786
808
  tokenOut: routeSummary.tokenOut,
@@ -788,10 +810,16 @@ export async function performSwap(params: {
788
810
  amountOut: routeSummary.amountOut,
789
811
  gasEstimate: routeSummary.gas,
790
812
  routerAddress,
791
- dexSources: routeSummary.swaps.map(swap => swap.exchange)
813
+ // Only try to access swaps if it exists
814
+ swapsCount: routeSummary.swaps ? routeSummary.swaps.length : 0,
815
+ // Only extract exchange names if swaps exists and has the expected structure
816
+ dexSources: routeSummary.swaps && Array.isArray(routeSummary.swaps)
817
+ ? routeSummary.swaps.map(swap => swap?.exchange || 'unknown').filter(Boolean)
818
+ : ['unknown']
792
819
  });
793
820
 
794
- console.log(' Building executable transaction...');
821
+ console.log('Building executable transaction...');
822
+
795
823
  const buildResponse = await buildKyberSwapTransaction(
796
824
  params.chainId,
797
825
  routeSummary,
@@ -802,6 +830,9 @@ export async function performSwap(params: {
802
830
  params.clientId || 'MyWalletApp'
803
831
  );
804
832
 
833
+ // Debug: Log build response
834
+ console.log('Build response:', JSON.stringify(buildResponse, null, 2));
835
+
805
836
  if (!buildResponse.data || !buildResponse.data.data) {
806
837
  throw new Error('Failed to build transaction data');
807
838
  }
@@ -826,6 +857,16 @@ export async function performSwap(params: {
826
857
 
827
858
  } catch (error) {
828
859
  console.error('❌ KyberSwap aggregation failed:', error);
860
+
861
+ // More detailed error logging
862
+ if (error instanceof Error) {
863
+ console.error('Error details:', {
864
+ message: error.message,
865
+ stack: error.stack,
866
+ name: error.name
867
+ });
868
+ }
869
+
829
870
  throw new Error(`Swap preparation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
830
871
  }
831
872
  }
@@ -838,6 +879,10 @@ export function isChainSupportedByKyber(chainId: string): boolean {
838
879
  return chainId in KYBER_SUPPORTED_CHAINS;
839
880
  }
840
881
 
882
+ export function isChainSupportedByDebonk(chainId: string): boolean {
883
+ return chainId in DESERIALIZED_SUPPORTED_CHAINS;
884
+ }
885
+
841
886
  export function getNativeTokenAddress(): string {
842
887
  return '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
843
888
  }
@@ -878,4 +923,24 @@ export function prepareSwapParams(
878
923
  tokenOutAddress,
879
924
  formattedAmountIn
880
925
  };
926
+ }
927
+
928
+ /**
929
+ * Normalize token address for Debonk
930
+ * Converts 'native' or variations to the standard 0xEeeee... address
931
+ */
932
+ // export function normalizeTokenAddressForDebonk(tokenAddress: string): string {
933
+ // if (tokenAddress === 'native' ||
934
+ // tokenAddress.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee') {
935
+ // return getNativeTokenAddress();
936
+ // }
937
+ // return tokenAddress;
938
+ // }
939
+
940
+ /**
941
+ * Convert slippage from basis points to percentage for Debonk
942
+ * Input: 50 (0.5% in bps) -> Output: 0.5 (percentage)
943
+ */
944
+ export function convertSlippageForDebonk(slippageBps: number): number {
945
+ return slippageBps / 100;
881
946
  }
package/utils/index.ts CHANGED
@@ -6,4 +6,6 @@ export * from "./evm"
6
6
  export * from "./svm"
7
7
  export * from "./bip32"
8
8
  export * from "./types"
9
- export * from "./constant"
9
+ export * from "./constant"
10
+ export * from "bs58"
11
+ export * from "@solana/web3.js"