@rhea-finance/cross-chain-aggregation-dex 0.1.2 → 0.1.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/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var Big2 = require('big.js');
3
+ var Big3 = require('big.js');
4
4
 
5
5
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
6
 
7
- var Big2__default = /*#__PURE__*/_interopDefault(Big2);
7
+ var Big3__default = /*#__PURE__*/_interopDefault(Big3);
8
8
 
9
9
  // src/types/index.ts
10
10
  function requiresRecipient(params) {
@@ -66,28 +66,18 @@ function setBluechipTokensConfig(config) {
66
66
  }
67
67
  function getBluechipTokensConfig() {
68
68
  if (!bluechipTokensConfig) {
69
- logger.warn(
70
- "getBluechipTokensConfig - Bluechip tokens config not set, returning empty config"
71
- );
72
69
  return {};
73
70
  }
74
71
  return bluechipTokensConfig;
75
72
  }
76
73
  function normalizeTokenId(tokenId, wrapNearContractId = "wrap.near") {
77
74
  if (!tokenId) {
78
- logger.error("normalizeTokenId - Empty tokenId:", tokenId);
79
75
  return "";
80
76
  }
81
77
  let normalized = tokenId.replace(/^nep141:/, "");
82
78
  if (normalized === "near") {
83
79
  normalized = wrapNearContractId;
84
80
  }
85
- if (!normalized) {
86
- logger.error("normalizeTokenId - Result is empty:", {
87
- tokenId,
88
- normalized
89
- });
90
- }
91
81
  return normalized;
92
82
  }
93
83
  function isNearIntentsSupportedToken(token, bluechipTokens) {
@@ -134,9 +124,6 @@ function findBestBluechipToken(bluechipTokens, wrapNearContractId = "wrap.near")
134
124
  });
135
125
  }
136
126
  if (preferredTokens.length === 0) {
137
- logger.warn(
138
- "findBestBluechipToken - No preferred tokens found, using wrap.near"
139
- );
140
127
  return {
141
128
  address: wrapNearContractId,
142
129
  symbol: "wNEAR",
@@ -144,7 +131,6 @@ function findBestBluechipToken(bluechipTokens, wrapNearContractId = "wrap.near")
144
131
  chain: "near"
145
132
  };
146
133
  }
147
- logger.debug("findBestBluechipToken - Selected token:", preferredTokens[0]);
148
134
  return preferredTokens[0];
149
135
  }
150
136
  function convertSlippageToBasisPoints(slippage) {
@@ -198,10 +184,6 @@ function formatGasToTgas(gasInYoctoNEAR) {
198
184
  const tgasBigInt = gasBigInt / BigInt("1000000000000");
199
185
  return tgasBigInt.toString();
200
186
  } catch (error) {
201
- logger.error("formatGasToTgas - Error formatting gas:", {
202
- gasInYoctoNEAR,
203
- error
204
- });
205
187
  return "0";
206
188
  }
207
189
  }
@@ -247,6 +229,13 @@ function formatGasString(gas) {
247
229
  }
248
230
  return gasStr;
249
231
  }
232
+ function selectBestQuote(quotes) {
233
+ return quotes.reduce((best, current) => {
234
+ const bestAmount = new Big3__default.default(best.quote.amountOut);
235
+ const currentAmount = new Big3__default.default(current.quote.amountOut);
236
+ return currentAmount.gt(bestAmount) ? current : best;
237
+ });
238
+ }
250
239
  var NearSmartRouter = class {
251
240
  constructor(config) {
252
241
  this.findPathAdapter = config.findPathAdapter;
@@ -290,16 +279,6 @@ var NearSmartRouter = class {
290
279
  this.wrapNearContractId
291
280
  );
292
281
  if (!normalizedTokenIn || !normalizedTokenOut) {
293
- logger.error("SmartRouter quote - Invalid token addresses:", {
294
- tokenIn: {
295
- original: tokenIn.address,
296
- normalized: normalizedTokenIn
297
- },
298
- tokenOut: {
299
- original: tokenOut.address,
300
- normalized: normalizedTokenOut
301
- }
302
- });
303
282
  return {
304
283
  success: false,
305
284
  tokenIn: params.tokenIn,
@@ -308,18 +287,11 @@ var NearSmartRouter = class {
308
287
  amountOut: "0",
309
288
  minAmountOut: "0",
310
289
  routes: [],
311
- error: `Invalid token address: tokenIn=${normalizedTokenIn || "empty"}, tokenOut=${normalizedTokenOut || "empty"}`
290
+ error: "Invalid token address"
312
291
  };
313
292
  }
314
293
  const slippageBps = convertSlippageToBasisPoints(slippage);
315
294
  const slippageDecimalForApi = slippageBps / 1e4;
316
- logger.debug("SmartRouter quote - Calling findPath:", {
317
- tokenIn: normalizedTokenIn,
318
- tokenOut: normalizedTokenOut,
319
- amountIn,
320
- slippage: slippageDecimalForApi,
321
- slippageBps
322
- });
323
295
  const response = await this.findPathAdapter.findPath({
324
296
  tokenIn: normalizedTokenIn,
325
297
  tokenOut: normalizedTokenOut,
@@ -327,11 +299,6 @@ var NearSmartRouter = class {
327
299
  slippage: slippageDecimalForApi,
328
300
  supportLedger: false
329
301
  });
330
- logger.debug("SmartRouter quote - findPath response:", {
331
- result_code: response?.result_code,
332
- result_msg: response?.result_msg || response?.result_message,
333
- hasRoutes: !!response?.result_data?.routes?.length
334
- });
335
302
  if (response?.result_code !== 0 || !response?.result_data?.routes?.length) {
336
303
  return {
337
304
  success: false,
@@ -345,7 +312,7 @@ var NearSmartRouter = class {
345
312
  };
346
313
  }
347
314
  const { routes: serverRoutes, amount_out } = response.result_data;
348
- const slippageDecimal = new Big2__default.default(slippageBps).div(1e4);
315
+ const slippageDecimal = new Big3__default.default(slippageBps).div(1e4);
349
316
  const routes = serverRoutes.map((route) => ({
350
317
  pools: route.pools.map((pool) => ({
351
318
  pool_id: Number(pool.pool_id),
@@ -358,8 +325,8 @@ var NearSmartRouter = class {
358
325
  amountIn,
359
326
  amountOut: route.amount_out || amount_out || "0"
360
327
  }));
361
- const amountOut = new Big2__default.default(amount_out || 0);
362
- const minAmountOut = amountOut.mul(new Big2__default.default(1).minus(slippageDecimal)).toFixed(0, Big2__default.default.roundDown);
328
+ const amountOut = new Big3__default.default(amount_out || 0);
329
+ const minAmountOut = amountOut.mul(new Big3__default.default(1).minus(slippageDecimal)).toFixed(0, Big3__default.default.roundDown);
363
330
  return {
364
331
  success: true,
365
332
  tokenIn,
@@ -432,10 +399,6 @@ var NearSmartRouter = class {
432
399
  isRegistered = false;
433
400
  }
434
401
  if (!isRegistered) {
435
- logger.debug("SmartRouter - Registering recipient account:", {
436
- contractId: quote.tokenOut.address,
437
- accountId: finalRecipient
438
- });
439
402
  transactions.push({
440
403
  contractId: quote.tokenOut.address,
441
404
  methodName: "storage_deposit",
@@ -456,15 +419,6 @@ var NearSmartRouter = class {
456
419
  if (finalRecipient) {
457
420
  swapMsg.swap_out_recipient = finalRecipient;
458
421
  }
459
- logger.debug("SmartRouter - Executing swap:", {
460
- contractId: quote.tokenIn.address,
461
- receiver_id: this.refExchangeId,
462
- amount: quote.amountIn,
463
- swapMsg,
464
- swapActionsCount: swapActions.length,
465
- recipient: finalRecipient,
466
- tokenOut: quote.tokenOut?.address
467
- });
468
422
  transactions.push({
469
423
  contractId: quote.tokenIn.address,
470
424
  methodName: "ft_transfer_call",
@@ -527,11 +481,7 @@ var AggregateDexRouter = class {
527
481
  this.configAdapter = config.configAdapter;
528
482
  this.aggregateDexContractId = this.configAdapter.getAggregateDexContractId?.() || "";
529
483
  this.wrapNearContractId = this.configAdapter.getWrapNearContractId();
530
- if (!this.aggregateDexContractId) {
531
- logger.error(
532
- "AggregateDexRouter - AGGREGATE_DEX_CONTRACT_ID not configured"
533
- );
534
- }
484
+ if (!this.aggregateDexContractId) ;
535
485
  }
536
486
  /**
537
487
  * Get Router capabilities
@@ -561,15 +511,11 @@ var AggregateDexRouter = class {
561
511
  amountOut: "0",
562
512
  minAmountOut: "0",
563
513
  routes: [],
564
- error: "V2 Router requires sender and recipient parameters"
514
+ error: "Missing sender or recipient"
565
515
  };
566
516
  }
567
517
  const { tokenIn, tokenOut, amountIn, slippage, sender, recipient } = params;
568
518
  if (!sender || !recipient) {
569
- logger.error("AggregateDexRouter quote - Missing sender or recipient:", {
570
- sender,
571
- recipient
572
- });
573
519
  return {
574
520
  success: false,
575
521
  tokenIn: params.tokenIn,
@@ -578,7 +524,7 @@ var AggregateDexRouter = class {
578
524
  amountOut: "0",
579
525
  minAmountOut: "0",
580
526
  routes: [],
581
- error: `V2 Router requires non-empty sender and recipient. Got sender="${sender}", recipient="${recipient}"`
527
+ error: "Missing sender or recipient"
582
528
  };
583
529
  }
584
530
  if (!tokenIn?.address || !tokenOut?.address) {
@@ -602,16 +548,6 @@ var AggregateDexRouter = class {
602
548
  this.wrapNearContractId
603
549
  );
604
550
  if (!normalizedTokenIn || !normalizedTokenOut) {
605
- logger.error("AggregateDexRouter quote - Invalid token addresses:", {
606
- tokenIn: {
607
- original: tokenIn.address,
608
- normalized: normalizedTokenIn
609
- },
610
- tokenOut: {
611
- original: tokenOut.address,
612
- normalized: normalizedTokenOut
613
- }
614
- });
615
551
  return {
616
552
  success: false,
617
553
  tokenIn: params.tokenIn,
@@ -620,7 +556,7 @@ var AggregateDexRouter = class {
620
556
  amountOut: "0",
621
557
  minAmountOut: "0",
622
558
  routes: [],
623
- error: `Invalid token address: tokenIn=${normalizedTokenIn || "empty"}, tokenOut=${normalizedTokenOut || "empty"}`
559
+ error: "Invalid token address"
624
560
  };
625
561
  }
626
562
  const slippageBps = convertSlippageToBasisPoints(slippage);
@@ -643,7 +579,7 @@ var AggregateDexRouter = class {
643
579
  amountOut: "0",
644
580
  minAmountOut: "0",
645
581
  routes: [],
646
- error: response.result_message || "V2 Router API call failed"
582
+ error: "Failed to get quote"
647
583
  };
648
584
  }
649
585
  const {
@@ -671,7 +607,6 @@ var AggregateDexRouter = class {
671
607
  slippage
672
608
  };
673
609
  } catch (error) {
674
- logger.error("AggregateDexRouter quote - Error:", error);
675
610
  return {
676
611
  success: false,
677
612
  tokenIn: params.tokenIn,
@@ -680,7 +615,7 @@ var AggregateDexRouter = class {
680
615
  amountOut: "0",
681
616
  minAmountOut: "0",
682
617
  routes: [],
683
- error: error?.message || "Quote failed"
618
+ error: "Failed to get quote"
684
619
  };
685
620
  }
686
621
  }
@@ -696,65 +631,61 @@ var AggregateDexRouter = class {
696
631
  recipient: depositAddress
697
632
  });
698
633
  }
699
- async reFetchQuoteWithBalance(quoteParams, actualBalance, context) {
700
- const balanceBig = new Big2__default.default(actualBalance);
634
+ async reFetchQuoteWithBalance(quoteParams, actualBalance, _context) {
635
+ const balanceBig = new Big3__default.default(actualBalance);
701
636
  const adjustedParams = {
702
637
  ...quoteParams,
703
638
  amountIn: balanceBig.toFixed(0)
704
639
  };
705
- logger.warn(`AggregateDexRouter - ${context}: re-fetching quote with actual balance:`, {
706
- requestedAmount: quoteParams.amountIn,
707
- actualBalance
708
- });
709
640
  const adjustedQuote = await this.quote(adjustedParams);
710
641
  if (adjustedQuote.success && adjustedQuote.routerMsg && adjustedQuote.signature) {
711
642
  return adjustedQuote;
712
643
  } else {
713
- throw new Error(`Failed to re-fetch quote with actual balance: ${adjustedQuote.error || "Unknown error"}`);
644
+ throw new Error("Failed to get quote");
714
645
  }
715
646
  }
716
647
  async ensureQuoteAmountWithinBalance(quoteParams, actualBalance, context) {
717
- const requestedAmountBig = new Big2__default.default(quoteParams.amountIn);
718
- const balanceBig = new Big2__default.default(actualBalance);
648
+ const requestedAmountBig = new Big3__default.default(quoteParams.amountIn);
649
+ const balanceBig = new Big3__default.default(actualBalance);
719
650
  const isNativeNear = (quoteParams.tokenIn.symbol === "NEAR" || quoteParams.tokenIn.address === "near" || !quoteParams.tokenIn.address && quoteParams.tokenIn.symbol === "NEAR") && quoteParams.tokenIn.address !== this.wrapNearContractId;
720
651
  let effectiveBalanceBig = balanceBig;
721
652
  let effectiveBalanceStr = actualBalance;
722
653
  if (isNativeNear) {
723
- const reserveAmount = new Big2__default.default("50000000000000000000000");
654
+ const reserveAmount = new Big3__default.default("50000000000000000000000");
724
655
  if (balanceBig.gt(reserveAmount)) {
725
656
  effectiveBalanceBig = balanceBig.minus(reserveAmount);
726
657
  effectiveBalanceStr = effectiveBalanceBig.toFixed(0);
727
658
  } else {
728
- effectiveBalanceBig = new Big2__default.default(0);
659
+ effectiveBalanceBig = new Big3__default.default(0);
729
660
  effectiveBalanceStr = "0";
730
661
  }
731
662
  }
732
663
  if (requestedAmountBig.gt(effectiveBalanceBig) && balanceBig.gt(0)) {
733
- return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (requested amount exceeds available balance${isNativeNear ? " minus gas reserve" : ""})`);
664
+ return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, context);
734
665
  }
735
666
  if (balanceBig.gt(0) && requestedAmountBig.lt(balanceBig)) {
736
667
  const diff = balanceBig.minus(requestedAmountBig);
737
668
  const diffPercent = diff.div(balanceBig).times(100);
738
669
  const isMaxSwap = diffPercent.lt(0.1) || diff.lt(1e3);
739
670
  if (isMaxSwap) {
740
- return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (MAX swap detected, using ${isNativeNear ? "balance minus gas reserve" : "actual balance"})`);
671
+ return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, context);
741
672
  }
742
673
  }
743
674
  const quote = await this.quote(quoteParams);
744
675
  if (!quote.success) {
745
- throw new Error(`Failed to fetch quote: ${quote.error || "Unknown error"}`);
676
+ throw new Error("Failed to get quote");
746
677
  }
747
678
  if (quote.amountIn !== quoteParams.amountIn) {
748
- const apiAmountBig = new Big2__default.default(quote.amountIn);
679
+ const apiAmountBig = new Big3__default.default(quote.amountIn);
749
680
  if (apiAmountBig.gt(effectiveBalanceBig) && balanceBig.gt(0)) {
750
- return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (API returned amount_in exceeds available balance)`);
681
+ return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, context);
751
682
  }
752
683
  if (apiAmountBig.lt(balanceBig) && balanceBig.gt(0)) {
753
684
  const diff = balanceBig.minus(apiAmountBig);
754
685
  const diffPercent = diff.div(balanceBig).times(100);
755
686
  const isMaxSwap = diffPercent.lt(0.1) || diff.lt(1e3);
756
687
  if (isMaxSwap) {
757
- return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, `${context} (API returned amount_in close to balance, MAX swap detected)`);
688
+ return await this.reFetchQuoteWithBalance(quoteParams, effectiveBalanceStr, context);
758
689
  }
759
690
  }
760
691
  }
@@ -765,7 +696,7 @@ var AggregateDexRouter = class {
765
696
  if (!requiresRecipientInExecute(params)) {
766
697
  return {
767
698
  success: false,
768
- error: "V2 Router requires sender and receiveUser parameters"
699
+ error: "Missing sender or receiveUser"
769
700
  };
770
701
  }
771
702
  const { quote, sender, receiveUser } = params;
@@ -778,13 +709,13 @@ var AggregateDexRouter = class {
778
709
  if (!receiveUser || receiveUser.trim() === "") {
779
710
  return {
780
711
  success: false,
781
- error: "receiveUser (depositAddress) is required"
712
+ error: "Missing receiveUser"
782
713
  };
783
714
  }
784
715
  if (receiveUser.startsWith("0x") && receiveUser.length === 42) {
785
716
  return {
786
717
  success: false,
787
- error: `receiveUser appears to be an EVM address (${receiveUser}). For NEAR chain swaps, depositAddress must be a NEAR account (64 hex chars or .near format)`
718
+ error: "Invalid receiveUser address"
788
719
  };
789
720
  }
790
721
  const slippage = quote.slippage || 5e-3;
@@ -814,10 +745,9 @@ var AggregateDexRouter = class {
814
745
  "Re-fetching quote with receiveUser"
815
746
  );
816
747
  } catch (error) {
817
- logger.error("AggregateDexRouter - Failed to fetch quote with receiveUser:", error);
818
748
  return {
819
749
  success: false,
820
- error: `Failed to fetch quote with receiveUser="${receiveUser}": ${error?.message || "Unknown error"}`
750
+ error: "Failed to get quote"
821
751
  };
822
752
  }
823
753
  const routerMsg = finalQuote.routerMsg;
@@ -825,7 +755,7 @@ var AggregateDexRouter = class {
825
755
  if (!routerMsg || !signature) {
826
756
  return {
827
757
  success: false,
828
- error: `Quote fetched with receiveUser="${receiveUser}" is missing routerMsg or signature.`
758
+ error: "Failed to get quote"
829
759
  };
830
760
  }
831
761
  const tokens = finalQuote.tokens || [];
@@ -892,14 +822,7 @@ var AggregateDexRouter = class {
892
822
  const receiveUserStorageBalance = await getStorageBalance(
893
823
  finalQuote.tokenOut.address,
894
824
  receiveUser
895
- ).catch((error) => {
896
- logger.warn("AggregateDexRouter - Failed to check receiveUser storage balance:", {
897
- receiveUser,
898
- tokenOut: finalQuote.tokenOut.address,
899
- error: error?.message
900
- });
901
- return null;
902
- });
825
+ ).catch(() => null);
903
826
  if (!receiveUserStorageBalance) {
904
827
  transactions.push({
905
828
  contractId: finalQuote.tokenOut.address,
@@ -943,8 +866,8 @@ var AggregateDexRouter = class {
943
866
  (_, index) => !registeredStatus[index]
944
867
  );
945
868
  if (unregisteredTokens.length > 0) {
946
- const depositPerToken = new Big2__default.default("0.005").mul(
947
- new Big2__default.default("1000000000000000000000000")
869
+ const depositPerToken = new Big3__default.default("0.005").mul(
870
+ new Big3__default.default("1000000000000000000000000")
948
871
  );
949
872
  const totalDeposit = depositPerToken.mul(unregisteredTokens.length);
950
873
  transactions.push({
@@ -984,10 +907,9 @@ var AggregateDexRouter = class {
984
907
  "Final balance check before execution"
985
908
  );
986
909
  } catch (error) {
987
- logger.error("AggregateDexRouter - Failed final balance check:", error);
988
910
  return {
989
911
  success: false,
990
- error: `Failed final balance check: ${error?.message || "Unknown error"}`
912
+ error: "Failed to get quote"
991
913
  };
992
914
  }
993
915
  const finalAmountToTransfer = finalQuoteForExecution.amountIn;
@@ -1018,14 +940,13 @@ var AggregateDexRouter = class {
1018
940
  } else {
1019
941
  return {
1020
942
  success: false,
1021
- error: result.message || "Execute swap failed"
943
+ error: "Execute swap failed"
1022
944
  };
1023
945
  }
1024
946
  } catch (error) {
1025
- logger.error("AggregateDexRouter executeSwap - Error:", error);
1026
947
  return {
1027
948
  success: false,
1028
- error: error?.message || "Execute swap failed"
949
+ error: "Execute swap failed"
1029
950
  };
1030
951
  }
1031
952
  }
@@ -1043,10 +964,6 @@ var AggregateDexRouter = class {
1043
964
  }
1044
965
  });
1045
966
  } catch (error) {
1046
- logger.error(
1047
- "AggregateDexRouter - Failed to query user tokens registered:",
1048
- error
1049
- );
1050
967
  return tokens.map(() => false);
1051
968
  }
1052
969
  }
@@ -1055,13 +972,15 @@ async function completeQuote(params, config) {
1055
972
  const {
1056
973
  sourceToken,
1057
974
  targetToken,
1058
- sourceChain,
975
+ sourceChain: _sourceChain,
976
+ // Reserved for future use
1059
977
  targetChain: _targetChain,
1060
978
  // Reserved for future use
1061
979
  amountIn,
1062
980
  slippage,
1063
981
  recipient,
1064
- refundTo
982
+ refundTo,
983
+ customRecipientMsg
1065
984
  } = params;
1066
985
  const {
1067
986
  intentsQuotationAdapter,
@@ -1069,7 +988,8 @@ async function completeQuote(params, config) {
1069
988
  dexRouter,
1070
989
  bluechipTokens,
1071
990
  configAdapter,
1072
- currentUserAddress
991
+ currentUserAddress,
992
+ isIntentsSupportedToken: customIsIntentsSupportedToken
1073
993
  } = config;
1074
994
  const wrapNearContractId = configAdapter.getWrapNearContractId();
1075
995
  const routers = dexRouters || (dexRouter ? [dexRouter] : []);
@@ -1086,226 +1006,227 @@ async function completeQuote(params, config) {
1086
1006
  if (!targetToken?.address) {
1087
1007
  throw new Error("Target token address is required");
1088
1008
  }
1089
- const needsPreSwap = sourceChain === "near" && !isNearIntentsSupportedToken(sourceToken, bluechipTokens);
1009
+ const isTokenIntentsSupported = customIsIntentsSupportedToken ? customIsIntentsSupportedToken(sourceToken) : isNearIntentsSupportedToken(sourceToken, bluechipTokens);
1090
1010
  const bluechipToken = findBestBluechipToken(
1091
1011
  bluechipTokens,
1092
1012
  wrapNearContractId
1093
1013
  );
1094
1014
  if (!bluechipToken?.address) {
1095
- logger.error("DEX Aggregator - Failed to find bluechip token:", {
1096
- bluechipToken,
1097
- bluechipTokens
1098
- });
1099
1015
  throw new Error("Failed to find bluechip token address");
1100
1016
  }
1101
- logger.debug("DEX Aggregator - Using bluechip token:", {
1102
- address: bluechipToken.address,
1103
- symbol: bluechipToken.symbol,
1104
- decimals: bluechipToken.decimals
1105
- });
1106
- let preSwapQuote = null;
1107
- let bestRouter = null;
1108
- if (needsPreSwap) {
1109
- if (!sourceToken?.address) {
1110
- throw new Error("Source token address is required");
1111
- }
1112
- logger.debug("DEX Aggregator - Pre-swap quote params:", {
1113
- tokenIn: {
1114
- address: sourceToken.address,
1115
- symbol: sourceToken.symbol
1116
- },
1117
- tokenOut: {
1118
- address: bluechipToken.address,
1119
- symbol: bluechipToken.symbol
1120
- },
1017
+ const quotePaths = [];
1018
+ routers.forEach((router, index) => {
1019
+ const routeType = index === 0 ? "v1" : "v2";
1020
+ const capabilities = router.getCapabilities();
1021
+ const quoteParams = capabilities.requiresRecipient ? {
1022
+ tokenIn: sourceToken,
1023
+ tokenOut: bluechipToken,
1121
1024
  amountIn,
1122
1025
  slippage,
1123
- routersCount: routers.length,
1124
- userAddress
1125
- });
1126
- const quotes = await Promise.allSettled(
1127
- routers.map((router) => {
1128
- const capabilities = router.getCapabilities();
1129
- const quoteParams = capabilities.requiresRecipient ? {
1130
- tokenIn: sourceToken,
1131
- tokenOut: bluechipToken,
1132
- amountIn,
1133
- slippage,
1134
- swapType: "EXACT_INPUT",
1135
- sender: userAddress,
1136
- recipient: userAddress
1137
- } : {
1138
- tokenIn: sourceToken,
1139
- tokenOut: bluechipToken,
1140
- amountIn,
1141
- slippage,
1142
- swapType: "EXACT_INPUT"
1143
- };
1144
- return router.quote(quoteParams);
1145
- })
1146
- );
1147
- const validQuotes = quotes.filter(
1148
- (r) => r.status === "fulfilled" && r.value.success
1149
- ).map((r) => r.value);
1150
- if (validQuotes.length === 0) {
1151
- const errors = quotes.map((r, index) => {
1152
- if (r.status === "rejected") {
1153
- return `Router ${index}: ${r.reason}`;
1026
+ swapType: "EXACT_INPUT",
1027
+ sender: userAddress,
1028
+ recipient: userAddress
1029
+ } : {
1030
+ tokenIn: sourceToken,
1031
+ tokenOut: bluechipToken,
1032
+ amountIn,
1033
+ slippage,
1034
+ swapType: "EXACT_INPUT"
1035
+ };
1036
+ quotePaths.push({
1037
+ type: routeType,
1038
+ router,
1039
+ promise: (async () => {
1040
+ const preSwapQuote = await router.quote(quoteParams);
1041
+ if (!preSwapQuote.success) {
1042
+ throw new Error("Failed to get quote");
1154
1043
  }
1155
- if (r.status === "fulfilled" && !r.value.success) {
1156
- return `Router ${index}: ${r.value.error}`;
1044
+ const bluechipKey = bluechipToken.symbol?.toUpperCase() === "WNEAR" ? "NEAR" : bluechipToken.symbol?.toUpperCase();
1045
+ const bluechipTokenConfig = bluechipKey && bluechipTokens[bluechipKey] || void 0;
1046
+ const normalizedSourceAsset = bluechipTokenConfig?.assetId ? bluechipTokenConfig.assetId : `nep141:${bluechipToken.address}`;
1047
+ let normalizedTargetAsset = targetToken.address;
1048
+ if (normalizedTargetAsset && !normalizedTargetAsset.startsWith("nep141:") && !normalizedTargetAsset.startsWith("nep245:") && normalizedTargetAsset.includes(".")) {
1049
+ normalizedTargetAsset = `nep141:${normalizeTokenId(
1050
+ normalizedTargetAsset,
1051
+ wrapNearContractId
1052
+ )}`;
1157
1053
  }
1158
- return null;
1159
- }).filter(Boolean);
1160
- logger.error("DEX Aggregator - All router quotes failed:", errors);
1161
- throw new Error(
1162
- `All router quotes failed: ${errors.join("; ")}`
1163
- );
1164
- }
1165
- const bestQuote = validQuotes.reduce((best, current) => {
1166
- const bestAmount = new Big2__default.default(best.amountOut);
1167
- const currentAmount = new Big2__default.default(current.amountOut);
1168
- return currentAmount.gt(bestAmount) ? current : best;
1169
- });
1170
- const bestQuoteIndex = validQuotes.indexOf(bestQuote);
1171
- bestRouter = routers[bestQuoteIndex];
1172
- preSwapQuote = bestQuote;
1173
- logger.debug("DEX Aggregator - Selected best router:", {
1174
- routerIndex: bestQuoteIndex,
1175
- amountOut: bestQuote.amountOut,
1176
- routerType: bestRouter.getCapabilities().requiresRecipient ? "V2 (Recipient)" : "V1 (Simple)"
1054
+ normalizedTargetAsset = normalizeDestinationAsset(normalizedTargetAsset, wrapNearContractId) || normalizedTargetAsset;
1055
+ const slippageBps = convertSlippageToBasisPoints(slippage);
1056
+ const intentsQuote = await intentsQuotationAdapter.quote({
1057
+ originAsset: normalizedSourceAsset,
1058
+ destinationAsset: normalizedTargetAsset,
1059
+ amount: preSwapQuote.amountOut,
1060
+ refundTo: refundTo || recipient,
1061
+ recipient,
1062
+ slippageTolerance: slippageBps,
1063
+ swapType: "FLEX_INPUT",
1064
+ ...customRecipientMsg ? { customRecipientMsg } : {}
1065
+ });
1066
+ if (intentsQuote.quoteStatus !== "success") {
1067
+ throw new Error("Failed to get quote");
1068
+ }
1069
+ return {
1070
+ intentsQuote,
1071
+ preSwapQuote,
1072
+ router,
1073
+ finalAmountOut: intentsQuote.quoteSuccessResult?.quote?.amountOut || "0"
1074
+ };
1075
+ })()
1177
1076
  });
1178
- const preSwapAmountOut = preSwapQuote.amountOut;
1179
- if (!preSwapAmountOut || new Big2__default.default(preSwapAmountOut).lte(0)) {
1180
- logger.error("DEX Aggregator - Pre-swap amountOut is invalid:", {
1181
- amountOut: preSwapAmountOut,
1182
- tokenIn: sourceToken,
1183
- tokenOut: bluechipToken
1184
- });
1185
- throw new Error(
1186
- "Pre-swap returned invalid amount: amount is too small or zero"
1187
- );
1188
- }
1189
- logger.debug("DEX Aggregator - Pre-swap quote success:", {
1190
- amountOut: preSwapAmountOut,
1191
- tokenOut: bluechipToken.symbol,
1192
- decimals: bluechipToken.decimals
1077
+ });
1078
+ if (isTokenIntentsSupported) {
1079
+ quotePaths.push({
1080
+ type: "intents",
1081
+ promise: (async () => {
1082
+ let normalizedSourceAsset;
1083
+ if (sourceToken.symbol) {
1084
+ const sourceKey = sourceToken.symbol.toUpperCase();
1085
+ const sourceTokenConfig = bluechipTokens[sourceKey];
1086
+ if (sourceTokenConfig?.assetId) {
1087
+ normalizedSourceAsset = sourceTokenConfig.assetId;
1088
+ } else {
1089
+ normalizedSourceAsset = normalizeTokenId(
1090
+ sourceToken.address,
1091
+ wrapNearContractId
1092
+ );
1093
+ if (!normalizedSourceAsset.startsWith("nep141:")) {
1094
+ normalizedSourceAsset = `nep141:${normalizedSourceAsset}`;
1095
+ }
1096
+ }
1097
+ } else {
1098
+ normalizedSourceAsset = normalizeTokenId(
1099
+ sourceToken.address,
1100
+ wrapNearContractId
1101
+ );
1102
+ if (!normalizedSourceAsset.startsWith("nep141:")) {
1103
+ normalizedSourceAsset = `nep141:${normalizedSourceAsset}`;
1104
+ }
1105
+ }
1106
+ let normalizedTargetAsset = targetToken.address;
1107
+ if (normalizedTargetAsset && !normalizedTargetAsset.startsWith("nep141:") && !normalizedTargetAsset.startsWith("nep245:") && normalizedTargetAsset.includes(".")) {
1108
+ normalizedTargetAsset = `nep141:${normalizeTokenId(
1109
+ normalizedTargetAsset,
1110
+ wrapNearContractId
1111
+ )}`;
1112
+ }
1113
+ normalizedTargetAsset = normalizeDestinationAsset(normalizedTargetAsset, wrapNearContractId) || normalizedTargetAsset;
1114
+ const slippageBps = convertSlippageToBasisPoints(slippage);
1115
+ const intentsQuote = await intentsQuotationAdapter.quote({
1116
+ originAsset: normalizedSourceAsset,
1117
+ destinationAsset: normalizedTargetAsset,
1118
+ amount: amountIn,
1119
+ refundTo: refundTo || recipient,
1120
+ recipient,
1121
+ slippageTolerance: slippageBps,
1122
+ swapType: "EXACT_INPUT",
1123
+ ...customRecipientMsg ? { customRecipientMsg } : {}
1124
+ });
1125
+ if (intentsQuote.quoteStatus !== "success") {
1126
+ throw new Error("Failed to get quote");
1127
+ }
1128
+ return {
1129
+ intentsQuote,
1130
+ finalAmountOut: intentsQuote.quoteSuccessResult?.quote?.amountOut || "0"
1131
+ };
1132
+ })()
1193
1133
  });
1194
1134
  }
1195
- let normalizedSourceAsset;
1196
- if (needsPreSwap) {
1197
- const bluechipKey = bluechipToken.symbol?.toUpperCase() === "WNEAR" ? "NEAR" : bluechipToken.symbol?.toUpperCase();
1198
- const bluechipTokenConfig = bluechipKey && bluechipTokens[bluechipKey] || void 0;
1199
- if (bluechipTokenConfig?.assetId) {
1200
- normalizedSourceAsset = bluechipTokenConfig.assetId;
1201
- logger.debug("Using bluechip token assetId for NearIntents:", {
1202
- symbol: bluechipToken.symbol,
1203
- assetId: normalizedSourceAsset,
1204
- contractAddress: bluechipToken.address
1135
+ const pathResults = await Promise.allSettled(
1136
+ quotePaths.map((p) => p.promise)
1137
+ );
1138
+ const validPaths = [];
1139
+ pathResults.forEach((result, index) => {
1140
+ const pathType = quotePaths[index].type;
1141
+ if (result.status === "fulfilled") {
1142
+ validPaths.push({
1143
+ type: pathType,
1144
+ ...result.value
1205
1145
  });
1206
- } else {
1207
- normalizedSourceAsset = `nep141:${bluechipToken.address}`;
1208
- logger.warn(
1209
- "Bluechip token assetId not found, using contractAddress with prefix:",
1210
- {
1211
- symbol: bluechipToken.symbol,
1212
- normalizedSourceAsset
1213
- }
1214
- );
1215
- }
1216
- } else {
1217
- if (sourceToken.symbol) {
1218
- const sourceKey = sourceToken.symbol.toUpperCase();
1219
- const sourceTokenConfig = bluechipTokens[sourceKey];
1220
- if (sourceTokenConfig?.assetId) {
1221
- normalizedSourceAsset = sourceTokenConfig.assetId;
1222
- } else {
1223
- normalizedSourceAsset = normalizeTokenId(
1224
- sourceToken.address,
1225
- wrapNearContractId
1226
- );
1227
- if (!normalizedSourceAsset.startsWith("nep141:")) {
1228
- normalizedSourceAsset = `nep141:${normalizedSourceAsset}`;
1229
- }
1230
- }
1231
- } else {
1232
- normalizedSourceAsset = normalizeTokenId(
1233
- sourceToken.address,
1234
- wrapNearContractId
1235
- );
1236
- if (!normalizedSourceAsset.startsWith("nep141:")) {
1237
- normalizedSourceAsset = `nep141:${normalizedSourceAsset}`;
1238
- }
1239
1146
  }
1240
- }
1241
- let normalizedTargetAsset = targetToken.address;
1242
- if (normalizedTargetAsset && !normalizedTargetAsset.startsWith("nep141:") && !normalizedTargetAsset.startsWith("nep245:") && normalizedTargetAsset.includes(".")) {
1243
- normalizedTargetAsset = `nep141:${normalizeTokenId(
1244
- normalizedTargetAsset,
1245
- wrapNearContractId
1246
- )}`;
1247
- }
1248
- normalizedTargetAsset = normalizeDestinationAsset(normalizedTargetAsset, wrapNearContractId) || normalizedTargetAsset;
1249
- const slippageBps = convertSlippageToBasisPoints(slippage);
1250
- const intentsAmount = needsPreSwap ? preSwapQuote.amountOut : amountIn;
1251
- logger.debug("DEX Aggregator - Calling NearIntents quotation:", {
1252
- originAsset: normalizedSourceAsset,
1253
- destinationAsset: normalizedTargetAsset,
1254
- amount: intentsAmount,
1255
- needsPreSwap,
1256
- preSwapAmountOut: needsPreSwap ? preSwapQuote.amountOut : void 0
1257
- });
1258
- const swapTypeForIntents = needsPreSwap ? "FLEX_INPUT" : void 0;
1259
- logger.debug("DEX Aggregator - swapType for NearIntents:", {
1260
- needsPreSwap,
1261
- swapType: swapTypeForIntents || "EXACT_INPUT (default)"
1262
- });
1263
- const intentsQuote = await intentsQuotationAdapter.quote({
1264
- originAsset: normalizedSourceAsset,
1265
- destinationAsset: normalizedTargetAsset,
1266
- amount: intentsAmount,
1267
- refundTo: refundTo || recipient,
1268
- recipient,
1269
- slippageTolerance: slippageBps,
1270
- swapType: swapTypeForIntents
1271
1147
  });
1272
- logger.debug("DEX Aggregator - NearIntents quotation result:", {
1273
- quoteStatus: intentsQuote.quoteStatus,
1274
- message: intentsQuote.message,
1275
- hasDepositAddress: !!intentsQuote.quoteSuccessResult?.quote?.depositAddress
1276
- });
1277
- if (intentsQuote.quoteStatus !== "success") {
1278
- const errorMessage = intentsQuote.message || "Unknown error";
1279
- logger.error("DEX Aggregator - NearIntents quote failed:", {
1280
- error: errorMessage,
1281
- originAsset: normalizedSourceAsset,
1282
- destinationAsset: normalizedTargetAsset,
1283
- amount: intentsAmount,
1284
- needsPreSwap,
1285
- preSwapAmountOut: needsPreSwap ? preSwapQuote.amountOut : void 0
1286
- });
1287
- throw new Error(`Intents quote failed: ${errorMessage}`);
1148
+ if (validPaths.length === 0) {
1149
+ throw new Error("Failed to get quote");
1288
1150
  }
1289
- const depositAddress = intentsQuote.quoteSuccessResult?.quote?.depositAddress || "";
1151
+ const bestPath = validPaths.reduce((best, current) => {
1152
+ const bestAmount = new Big3__default.default(best.finalAmountOut);
1153
+ const currentAmount = new Big3__default.default(current.finalAmountOut);
1154
+ return currentAmount.gt(bestAmount) ? current : best;
1155
+ });
1156
+ const depositAddress = bestPath.intentsQuote.quoteSuccessResult?.quote?.depositAddress || "";
1290
1157
  if (!depositAddress) {
1291
1158
  throw new Error("Deposit address not found in intents quote");
1292
1159
  }
1293
- const finalQuote = preSwapQuote;
1294
1160
  return {
1295
1161
  intents: {
1296
- quote: intentsQuote,
1162
+ quote: bestPath.intentsQuote,
1297
1163
  depositAddress
1298
1164
  },
1299
- preSwap: needsPreSwap && finalQuote && bestRouter ? {
1300
- quote: finalQuote,
1165
+ preSwap: bestPath.preSwapQuote && bestPath.router ? {
1166
+ quote: bestPath.preSwapQuote,
1301
1167
  tokenIn: sourceToken,
1302
1168
  tokenOut: bluechipToken,
1303
- executor: bestRouter
1169
+ executor: bestPath.router,
1170
+ routeType: bestPath.type
1304
1171
  } : void 0,
1305
- finalAmountOut: intentsQuote.quoteSuccessResult?.quote?.amountOut || "0"
1172
+ finalAmountOut: bestPath.finalAmountOut,
1173
+ routeType: bestPath.type
1306
1174
  };
1307
1175
  }
1308
1176
 
1177
+ // src/integration/quoteSameChainSwap.ts
1178
+ async function quoteSameChainSwap(params, dexRouters) {
1179
+ const {
1180
+ tokenIn,
1181
+ tokenOut,
1182
+ amountIn,
1183
+ slippage,
1184
+ recipient,
1185
+ currentUserAddress
1186
+ } = params;
1187
+ const quoteResults = await Promise.allSettled(
1188
+ dexRouters.map((router) => {
1189
+ const capabilities = router.getCapabilities();
1190
+ const quoteParams = capabilities.requiresRecipient ? {
1191
+ tokenIn,
1192
+ tokenOut,
1193
+ amountIn,
1194
+ slippage,
1195
+ swapType: "EXACT_INPUT",
1196
+ sender: currentUserAddress,
1197
+ recipient
1198
+ } : {
1199
+ tokenIn,
1200
+ tokenOut,
1201
+ amountIn,
1202
+ slippage,
1203
+ swapType: "EXACT_INPUT",
1204
+ recipient
1205
+ };
1206
+ return router.quote(quoteParams);
1207
+ })
1208
+ );
1209
+ const validQuotes = quoteResults.filter(
1210
+ (r) => r.status === "fulfilled" && r.value.success
1211
+ ).map((r, index) => ({
1212
+ quote: r.value,
1213
+ router: dexRouters[index]
1214
+ }));
1215
+ if (validQuotes.length === 0) {
1216
+ const errors = quoteResults.map((r, index) => {
1217
+ if (r.status === "rejected") {
1218
+ return `Router ${index}: ${r.reason}`;
1219
+ }
1220
+ if (r.status === "fulfilled" && !r.value.success) {
1221
+ return `Router ${index}: ${r.value.error}`;
1222
+ }
1223
+ return null;
1224
+ }).filter(Boolean);
1225
+ throw new Error(`All router quotes failed: ${errors.join("; ")}`);
1226
+ }
1227
+ return selectBestQuote(validQuotes);
1228
+ }
1229
+
1309
1230
  exports.AggregateDexRouter = AggregateDexRouter;
1310
1231
  exports.NearSmartRouter = NearSmartRouter;
1311
1232
  exports.completeQuote = completeQuote;
@@ -1318,8 +1239,10 @@ exports.isNearIntentsSupportedToken = isNearIntentsSupportedToken;
1318
1239
  exports.logger = logger;
1319
1240
  exports.normalizeDestinationAsset = normalizeDestinationAsset;
1320
1241
  exports.normalizeTokenId = normalizeTokenId;
1242
+ exports.quoteSameChainSwap = quoteSameChainSwap;
1321
1243
  exports.requiresRecipient = requiresRecipient;
1322
1244
  exports.requiresRecipientInExecute = requiresRecipientInExecute;
1245
+ exports.selectBestQuote = selectBestQuote;
1323
1246
  exports.setBluechipTokensConfig = setBluechipTokensConfig;
1324
1247
  //# sourceMappingURL=index.js.map
1325
1248
  //# sourceMappingURL=index.js.map