@rhea-finance/cross-chain-aggregation-dex 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,1295 @@
1
+ 'use strict';
2
+
3
+ var Big2 = require('big.js');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var Big2__default = /*#__PURE__*/_interopDefault(Big2);
8
+
9
+ // src/types/index.ts
10
+ function requiresRecipient(params) {
11
+ return "sender" in params && "recipient" in params;
12
+ }
13
+ function requiresRecipientInExecute(params) {
14
+ return "sender" in params && "receiveUser" in params;
15
+ }
16
+
17
+ // src/utils/logger.ts
18
+ var LOG_LEVELS = {
19
+ silent: 0,
20
+ error: 1,
21
+ warn: 2,
22
+ info: 3,
23
+ debug: 4
24
+ };
25
+ function getLogLevel() {
26
+ if (typeof process !== "undefined" && process.env?.LOG_LEVEL) {
27
+ const level = process.env.LOG_LEVEL.toLowerCase();
28
+ if (LOG_LEVELS[level] !== void 0) {
29
+ return level;
30
+ }
31
+ }
32
+ return typeof process !== "undefined" && process.env?.NODE_ENV === "production" ? "warn" : "debug";
33
+ }
34
+ var currentLogLevel = getLogLevel();
35
+ var currentLevelValue = LOG_LEVELS[currentLogLevel];
36
+ function shouldLog(level) {
37
+ return LOG_LEVELS[level] <= currentLevelValue;
38
+ }
39
+ var logger = {
40
+ debug: (...args) => {
41
+ if (shouldLog("debug")) {
42
+ console.debug(...args);
43
+ }
44
+ },
45
+ info: (...args) => {
46
+ if (shouldLog("info")) {
47
+ console.info(...args);
48
+ }
49
+ },
50
+ warn: (...args) => {
51
+ if (shouldLog("warn")) {
52
+ console.warn(...args);
53
+ }
54
+ },
55
+ error: (...args) => {
56
+ if (shouldLog("error")) {
57
+ console.error(...args);
58
+ }
59
+ }
60
+ };
61
+
62
+ // src/utils/index.ts
63
+ var bluechipTokensConfig = null;
64
+ function setBluechipTokensConfig(config) {
65
+ bluechipTokensConfig = config;
66
+ }
67
+ function getBluechipTokensConfig() {
68
+ if (!bluechipTokensConfig) {
69
+ logger.warn(
70
+ "getBluechipTokensConfig - Bluechip tokens config not set, returning empty config"
71
+ );
72
+ return {};
73
+ }
74
+ return bluechipTokensConfig;
75
+ }
76
+ function normalizeTokenId(tokenId, wrapNearContractId = "wrap.near") {
77
+ if (!tokenId) {
78
+ logger.error("normalizeTokenId - Empty tokenId:", tokenId);
79
+ return "";
80
+ }
81
+ let normalized = tokenId.replace(/^nep141:/, "");
82
+ if (normalized === "near") {
83
+ normalized = wrapNearContractId;
84
+ }
85
+ if (!normalized) {
86
+ logger.error("normalizeTokenId - Result is empty:", {
87
+ tokenId,
88
+ normalized
89
+ });
90
+ }
91
+ return normalized;
92
+ }
93
+ function isNearIntentsSupportedToken(token, bluechipTokens) {
94
+ if (!token?.symbol || !token?.address) {
95
+ return false;
96
+ }
97
+ const config = bluechipTokens || getBluechipTokensConfig();
98
+ const normalizedSymbol = token.symbol.toUpperCase();
99
+ const symbolKey = normalizedSymbol === "NEAR" || normalizedSymbol === "WNEAR" ? "NEAR" : normalizedSymbol;
100
+ const tokenConfig = config[symbolKey];
101
+ if (!tokenConfig) {
102
+ return false;
103
+ }
104
+ const normalizeAddress = (addr) => addr.replace(/^nep141:/, "").toLowerCase();
105
+ const tokenAddress = normalizeAddress(token.address);
106
+ const configAddress = normalizeAddress(tokenConfig.address || "");
107
+ const configAssetId = tokenConfig.assetId ? normalizeAddress(tokenConfig.assetId) : "";
108
+ return tokenAddress === configAddress || tokenAddress === configAssetId;
109
+ }
110
+ function findBestBluechipToken(bluechipTokens, wrapNearContractId = "wrap.near") {
111
+ const preferredTokens = [];
112
+ if (bluechipTokens.USDT?.address) {
113
+ preferredTokens.push({
114
+ address: bluechipTokens.USDT.address,
115
+ symbol: "USDT",
116
+ decimals: bluechipTokens.USDT.decimals || 6,
117
+ chain: "near"
118
+ });
119
+ }
120
+ if (bluechipTokens.USDC?.address) {
121
+ preferredTokens.push({
122
+ address: bluechipTokens.USDC.address,
123
+ symbol: "USDC",
124
+ decimals: bluechipTokens.USDC.decimals || 6,
125
+ chain: "near"
126
+ });
127
+ }
128
+ if (bluechipTokens.NEAR?.address) {
129
+ preferredTokens.push({
130
+ address: bluechipTokens.NEAR.address,
131
+ symbol: "wNEAR",
132
+ decimals: bluechipTokens.NEAR.decimals || 24,
133
+ chain: "near"
134
+ });
135
+ }
136
+ if (preferredTokens.length === 0) {
137
+ logger.warn(
138
+ "findBestBluechipToken - No preferred tokens found, using wrap.near"
139
+ );
140
+ return {
141
+ address: wrapNearContractId,
142
+ symbol: "wNEAR",
143
+ decimals: 24,
144
+ chain: "near"
145
+ };
146
+ }
147
+ logger.debug("findBestBluechipToken - Selected token:", preferredTokens[0]);
148
+ return preferredTokens[0];
149
+ }
150
+ function convertSlippageToBasisPoints(slippage) {
151
+ if (slippage >= 1) {
152
+ return Math.round(slippage);
153
+ }
154
+ if (slippage > 0 && slippage < 0.01) {
155
+ return Math.round(slippage * 1e4);
156
+ }
157
+ if (slippage >= 0.01 && slippage < 1) {
158
+ return Math.round(slippage * 100);
159
+ }
160
+ return Math.round(slippage);
161
+ }
162
+ function normalizeDestinationAsset(assetId, wrapNearContractId = "wrap.near") {
163
+ if (!assetId) return assetId;
164
+ if (assetId.startsWith("nep141:") || assetId.startsWith("nep245:")) {
165
+ return assetId;
166
+ }
167
+ if (assetId === "near" || assetId === "nep141:near") {
168
+ return `nep141:${wrapNearContractId}`;
169
+ }
170
+ if (assetId.includes(".")) {
171
+ return `nep141:${normalizeTokenId(assetId, wrapNearContractId)}`;
172
+ }
173
+ return assetId;
174
+ }
175
+ function formatGasToTgas(gasInYoctoNEAR) {
176
+ if (!gasInYoctoNEAR) return "0";
177
+ const gasStr = String(gasInYoctoNEAR);
178
+ if (/[eE]/.test(gasStr)) {
179
+ const match = gasStr.match(/^([+-]?\d*\.?\d+)[eE]([+-]?\d+)$/);
180
+ if (match) {
181
+ const base = match[1];
182
+ const exponent = parseInt(match[2], 10);
183
+ const [intPart, fracPart = ""] = base.split(".");
184
+ if (exponent > 0) {
185
+ const newIntPart = intPart + fracPart;
186
+ const zerosToAdd = exponent - fracPart.length;
187
+ if (zerosToAdd > 0) {
188
+ return (newIntPart + "0".repeat(zerosToAdd)).replace(/^0+/, "") || "0";
189
+ } else {
190
+ const pointPos = intPart.length + exponent;
191
+ return (newIntPart.slice(0, pointPos) + "." + newIntPart.slice(pointPos)).replace(/\.?0+$/, "");
192
+ }
193
+ }
194
+ }
195
+ }
196
+ try {
197
+ const gasBigInt = BigInt(gasStr.split(".")[0]);
198
+ const tgasBigInt = gasBigInt / BigInt("1000000000000");
199
+ return tgasBigInt.toString();
200
+ } catch (error) {
201
+ logger.error("formatGasToTgas - Error formatting gas:", {
202
+ gasInYoctoNEAR,
203
+ error
204
+ });
205
+ return "0";
206
+ }
207
+ }
208
+ function formatGasString(gas) {
209
+ if (typeof gas === "bigint") {
210
+ return gas.toString();
211
+ }
212
+ const gasStr = String(gas);
213
+ if (!/[eE]/.test(gasStr) && !gasStr.includes(".")) {
214
+ return gasStr;
215
+ }
216
+ if (/[eE]/.test(gasStr)) {
217
+ const match = gasStr.match(/^([+-]?\d*\.?\d+)[eE]([+-]?\d+)$/);
218
+ if (match) {
219
+ const base = match[1];
220
+ const exponent = parseInt(match[2], 10);
221
+ const [intPart, fracPart = ""] = base.split(".");
222
+ if (exponent > 0) {
223
+ const newIntPart = intPart + fracPart;
224
+ const zerosToAdd = exponent - fracPart.length;
225
+ if (zerosToAdd > 0) {
226
+ return (newIntPart + "0".repeat(zerosToAdd)).replace(/^0+/, "") || "0";
227
+ } else {
228
+ const pointPos = intPart.length + exponent;
229
+ const result = newIntPart.slice(0, pointPos) + "." + newIntPart.slice(pointPos);
230
+ return result.replace(/\.?0+$/, "").replace(/\.$/, "");
231
+ }
232
+ } else if (exponent < 0) {
233
+ const absExp = Math.abs(exponent);
234
+ const zerosToAdd = absExp - intPart.length;
235
+ if (zerosToAdd > 0) {
236
+ return "0." + "0".repeat(zerosToAdd - 1) + intPart.replace(/^-/, "") + fracPart;
237
+ } else {
238
+ const pointPos = intPart.length - absExp;
239
+ return intPart.slice(0, pointPos) + "." + intPart.slice(pointPos) + fracPart;
240
+ }
241
+ }
242
+ }
243
+ }
244
+ if (gasStr.includes(".")) {
245
+ const [intPart, fracPart = ""] = gasStr.split(".");
246
+ return intPart + fracPart;
247
+ }
248
+ return gasStr;
249
+ }
250
+ var NearSmartRouter = class {
251
+ constructor(config) {
252
+ this.findPathAdapter = config.findPathAdapter;
253
+ this.nearChainAdapter = config.nearChainAdapter;
254
+ this.configAdapter = config.configAdapter;
255
+ this.wrapNearContractId = this.configAdapter.getWrapNearContractId();
256
+ this.refExchangeId = this.configAdapter.getRefExchangeId();
257
+ this.tokenStorageDepositRead = this.configAdapter.getTokenStorageDepositRead?.() || "1250000000000000000000";
258
+ }
259
+ /**
260
+ * Get a swap quote (normalizes token ids and queries FindPath for routes).
261
+ */
262
+ async quote(params) {
263
+ try {
264
+ const {
265
+ tokenIn,
266
+ tokenOut,
267
+ amountIn,
268
+ slippage,
269
+ swapType: _swapType = "EXACT_INPUT"
270
+ // Currently not used, reserved for future use
271
+ } = params;
272
+ if (!tokenIn?.address || !tokenOut?.address) {
273
+ return {
274
+ success: false,
275
+ tokenIn: params.tokenIn,
276
+ tokenOut: params.tokenOut,
277
+ amountIn: params.amountIn,
278
+ amountOut: "0",
279
+ minAmountOut: "0",
280
+ routes: [],
281
+ error: "Missing token address"
282
+ };
283
+ }
284
+ const normalizedTokenIn = normalizeTokenId(
285
+ tokenIn.address,
286
+ this.wrapNearContractId
287
+ );
288
+ const normalizedTokenOut = normalizeTokenId(
289
+ tokenOut.address,
290
+ this.wrapNearContractId
291
+ );
292
+ 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
+ return {
304
+ success: false,
305
+ tokenIn: params.tokenIn,
306
+ tokenOut: params.tokenOut,
307
+ amountIn: params.amountIn,
308
+ amountOut: "0",
309
+ minAmountOut: "0",
310
+ routes: [],
311
+ error: `Invalid token address: tokenIn=${normalizedTokenIn || "empty"}, tokenOut=${normalizedTokenOut || "empty"}`
312
+ };
313
+ }
314
+ const slippageBps = convertSlippageToBasisPoints(slippage);
315
+ 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
+ const response = await this.findPathAdapter.findPath({
324
+ tokenIn: normalizedTokenIn,
325
+ tokenOut: normalizedTokenOut,
326
+ amountIn: String(amountIn),
327
+ slippage: slippageDecimalForApi,
328
+ supportLedger: false
329
+ });
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
+ if (response?.result_code !== 0 || !response?.result_data?.routes?.length) {
336
+ return {
337
+ success: false,
338
+ tokenIn,
339
+ tokenOut,
340
+ amountIn,
341
+ amountOut: "0",
342
+ minAmountOut: "0",
343
+ routes: [],
344
+ error: response?.result_msg || response?.result_message || "No route found"
345
+ };
346
+ }
347
+ const { routes: serverRoutes, amount_out } = response.result_data;
348
+ const slippageDecimal = new Big2__default.default(slippageBps).div(1e4);
349
+ const routes = serverRoutes.map((route) => ({
350
+ pools: route.pools.map((pool) => ({
351
+ pool_id: Number(pool.pool_id),
352
+ token_in: pool.token_in || normalizedTokenIn,
353
+ token_out: pool.token_out || normalizedTokenOut,
354
+ amount_in: pool.amount_in,
355
+ amount_out: pool.amount_out,
356
+ fee: pool.fee
357
+ })),
358
+ amountIn,
359
+ amountOut: route.amount_out || amount_out || "0"
360
+ }));
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);
363
+ return {
364
+ success: true,
365
+ tokenIn,
366
+ tokenOut,
367
+ amountIn,
368
+ amountOut: amountOut.toFixed(0),
369
+ minAmountOut,
370
+ routes,
371
+ // Save raw serverRoutes data for executeSwap
372
+ rawRoutes: serverRoutes
373
+ };
374
+ } catch (error) {
375
+ return {
376
+ success: false,
377
+ tokenIn: params.tokenIn,
378
+ tokenOut: params.tokenOut,
379
+ amountIn: params.amountIn,
380
+ amountOut: "0",
381
+ minAmountOut: "0",
382
+ routes: [],
383
+ error: error?.message || "Quote failed"
384
+ };
385
+ }
386
+ }
387
+ /**
388
+ * Execute a swap: optionally adds `storage_deposit` for the recipient, then calls REF via `ft_transfer_call`.
389
+ */
390
+ async executeSwap(params) {
391
+ try {
392
+ const { quote, recipient, depositAddress } = params;
393
+ if (!quote.success || !quote.routes.length) {
394
+ return {
395
+ success: false,
396
+ error: "Invalid quote"
397
+ };
398
+ }
399
+ const swapActions = [];
400
+ const routesToUse = quote.rawRoutes || quote.routes;
401
+ routesToUse.forEach((route) => {
402
+ const pools = route.pools || [];
403
+ pools.forEach((pool) => {
404
+ const poolCopy = { ...pool };
405
+ if (+(poolCopy?.amount_in || 0) == 0) {
406
+ delete poolCopy.amount_in;
407
+ }
408
+ poolCopy.pool_id = Number(poolCopy.pool_id);
409
+ swapActions.push(poolCopy);
410
+ });
411
+ });
412
+ if (!swapActions.length) {
413
+ return {
414
+ success: false,
415
+ error: "No swap actions"
416
+ };
417
+ }
418
+ const finalRecipient = depositAddress || recipient;
419
+ const transactions = [];
420
+ if (finalRecipient && quote.tokenOut?.address) {
421
+ let isRegistered = false;
422
+ try {
423
+ const storageBalance = await this.nearChainAdapter.view({
424
+ contractId: quote.tokenOut.address,
425
+ methodName: "storage_balance_of",
426
+ args: {
427
+ account_id: finalRecipient
428
+ }
429
+ });
430
+ isRegistered = !!storageBalance;
431
+ } catch (err) {
432
+ isRegistered = false;
433
+ }
434
+ if (!isRegistered) {
435
+ logger.debug("SmartRouter - Registering recipient account:", {
436
+ contractId: quote.tokenOut.address,
437
+ accountId: finalRecipient
438
+ });
439
+ transactions.push({
440
+ contractId: quote.tokenOut.address,
441
+ methodName: "storage_deposit",
442
+ args: {
443
+ account_id: finalRecipient,
444
+ registration_only: true
445
+ },
446
+ gas: "50",
447
+ expandDeposit: this.tokenStorageDepositRead
448
+ });
449
+ }
450
+ }
451
+ const swapMsg = {
452
+ force: 0,
453
+ actions: swapActions,
454
+ skip_unwrap_near: false
455
+ };
456
+ if (finalRecipient) {
457
+ swapMsg.swap_out_recipient = finalRecipient;
458
+ }
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
+ transactions.push({
469
+ contractId: quote.tokenIn.address,
470
+ methodName: "ft_transfer_call",
471
+ args: {
472
+ receiver_id: this.refExchangeId,
473
+ amount: quote.amountIn,
474
+ msg: JSON.stringify(swapMsg)
475
+ },
476
+ gas: "250",
477
+ // NEP-141 requires attaching 1 yoctoNEAR for certain calls.
478
+ expandDeposit: "1"
479
+ });
480
+ const result = await this.nearChainAdapter.call({
481
+ transactions
482
+ });
483
+ if (result.status === "success") {
484
+ return {
485
+ success: true,
486
+ txHash: result.txHash,
487
+ txHashArray: result.txHashArr || (result.txHash ? [result.txHash] : [])
488
+ };
489
+ } else {
490
+ return {
491
+ success: false,
492
+ error: result.message || "Execute swap failed"
493
+ };
494
+ }
495
+ } catch (error) {
496
+ return {
497
+ success: false,
498
+ error: error?.message || "Execute swap failed"
499
+ };
500
+ }
501
+ }
502
+ /**
503
+ * Get Router capabilities
504
+ */
505
+ getCapabilities() {
506
+ return {
507
+ requiresRecipient: false,
508
+ requiresFinalizeQuote: false,
509
+ requiresComplexRegistration: false,
510
+ supportedChain: "near"
511
+ };
512
+ }
513
+ /**
514
+ * Get supported chain
515
+ */
516
+ getSupportedChain() {
517
+ return "near";
518
+ }
519
+ };
520
+ var AggregateDexRouter = class {
521
+ constructor(config) {
522
+ this.NEW_ACCOUNT_STORAGE_COST = "1250000000000000000000";
523
+ // 0.00125 NEAR in yoctoNEAR
524
+ this.ONE_YOCTO_NEAR = "1";
525
+ this.swapMultiDexPathAdapter = config.swapMultiDexPathAdapter;
526
+ this.nearChainAdapter = config.nearChainAdapter;
527
+ this.configAdapter = config.configAdapter;
528
+ this.aggregateDexContractId = this.configAdapter.getAggregateDexContractId?.() || "";
529
+ this.wrapNearContractId = this.configAdapter.getWrapNearContractId();
530
+ if (!this.aggregateDexContractId) {
531
+ logger.error(
532
+ "AggregateDexRouter - AGGREGATE_DEX_CONTRACT_ID not configured"
533
+ );
534
+ }
535
+ }
536
+ /**
537
+ * Get Router capabilities
538
+ */
539
+ getCapabilities() {
540
+ return {
541
+ requiresRecipient: true,
542
+ requiresFinalizeQuote: false,
543
+ requiresComplexRegistration: true,
544
+ supportedChain: "near"
545
+ };
546
+ }
547
+ getSupportedChain() {
548
+ return "near";
549
+ }
550
+ /**
551
+ * Get a swap quote from V2 Router API
552
+ */
553
+ async quote(params) {
554
+ try {
555
+ if (!requiresRecipient(params)) {
556
+ return {
557
+ success: false,
558
+ tokenIn: params.tokenIn,
559
+ tokenOut: params.tokenOut,
560
+ amountIn: params.amountIn,
561
+ amountOut: "0",
562
+ minAmountOut: "0",
563
+ routes: [],
564
+ error: "V2 Router requires sender and recipient parameters"
565
+ };
566
+ }
567
+ const { tokenIn, tokenOut, amountIn, slippage, sender, recipient } = params;
568
+ if (!sender || !recipient) {
569
+ logger.error("AggregateDexRouter quote - Missing sender or recipient:", {
570
+ sender,
571
+ recipient
572
+ });
573
+ return {
574
+ success: false,
575
+ tokenIn: params.tokenIn,
576
+ tokenOut: params.tokenOut,
577
+ amountIn: params.amountIn,
578
+ amountOut: "0",
579
+ minAmountOut: "0",
580
+ routes: [],
581
+ error: `V2 Router requires non-empty sender and recipient. Got sender="${sender}", recipient="${recipient}"`
582
+ };
583
+ }
584
+ if (!tokenIn?.address || !tokenOut?.address) {
585
+ return {
586
+ success: false,
587
+ tokenIn: params.tokenIn,
588
+ tokenOut: params.tokenOut,
589
+ amountIn: params.amountIn,
590
+ amountOut: "0",
591
+ minAmountOut: "0",
592
+ routes: [],
593
+ error: "Missing token address"
594
+ };
595
+ }
596
+ const normalizedTokenIn = normalizeTokenId(
597
+ tokenIn.address,
598
+ this.wrapNearContractId
599
+ );
600
+ const normalizedTokenOut = normalizeTokenId(
601
+ tokenOut.address,
602
+ this.wrapNearContractId
603
+ );
604
+ 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
+ return {
616
+ success: false,
617
+ tokenIn: params.tokenIn,
618
+ tokenOut: params.tokenOut,
619
+ amountIn: params.amountIn,
620
+ amountOut: "0",
621
+ minAmountOut: "0",
622
+ routes: [],
623
+ error: `Invalid token address: tokenIn=${normalizedTokenIn || "empty"}, tokenOut=${normalizedTokenOut || "empty"}`
624
+ };
625
+ }
626
+ const slippageBps = convertSlippageToBasisPoints(slippage);
627
+ const slippageDecimalForApi = slippageBps / 1e4;
628
+ logger.debug("AggregateDexRouter quote - Calling swapMultiDexPath:", {
629
+ tokenIn: normalizedTokenIn,
630
+ tokenOut: normalizedTokenOut,
631
+ amountIn,
632
+ slippage: slippageDecimalForApi,
633
+ sender,
634
+ recipient
635
+ });
636
+ const response = await this.swapMultiDexPathAdapter.swapMultiDexPath({
637
+ amountIn: String(amountIn),
638
+ tokenIn: normalizedTokenIn,
639
+ tokenOut: normalizedTokenOut,
640
+ slippage: slippageDecimalForApi,
641
+ pathDeep: 2,
642
+ user: sender,
643
+ receiveUser: recipient
644
+ });
645
+ logger.debug("AggregateDexRouter quote - swapMultiDexPath response:", {
646
+ result_code: response?.result_code,
647
+ result_message: response?.result_message,
648
+ hasData: !!response?.result_data
649
+ });
650
+ if (response.result_code !== 0 || !response.result_data) {
651
+ return {
652
+ success: false,
653
+ tokenIn,
654
+ tokenOut,
655
+ amountIn,
656
+ amountOut: "0",
657
+ minAmountOut: "0",
658
+ routes: [],
659
+ error: response.result_message || "V2 Router API call failed"
660
+ };
661
+ }
662
+ const {
663
+ amount_in,
664
+ amount_out,
665
+ min_amount_out,
666
+ msg,
667
+ signature,
668
+ tokens,
669
+ dexs
670
+ } = response.result_data;
671
+ return {
672
+ success: true,
673
+ tokenIn,
674
+ tokenOut,
675
+ amountIn: amount_in || amountIn,
676
+ amountOut: amount_out || "0",
677
+ minAmountOut: min_amount_out || "0",
678
+ routes: [],
679
+ routerMsg: msg,
680
+ signature,
681
+ tokens: tokens || [],
682
+ dexs: dexs || [],
683
+ recipient,
684
+ slippage
685
+ };
686
+ } catch (error) {
687
+ logger.error("AggregateDexRouter quote - Error:", error);
688
+ return {
689
+ success: false,
690
+ tokenIn: params.tokenIn,
691
+ tokenOut: params.tokenOut,
692
+ amountIn: params.amountIn,
693
+ amountOut: "0",
694
+ minAmountOut: "0",
695
+ routes: [],
696
+ error: error?.message || "Quote failed"
697
+ };
698
+ }
699
+ }
700
+ /**
701
+ * Finalize quote with depositAddress (deprecated)
702
+ *
703
+ * @deprecated No longer needed. executeSwap automatically fetches final quote using receiveUser (depositAddress).
704
+ * Kept for interface compatibility only.
705
+ */
706
+ async finalizeQuote(params, depositAddress) {
707
+ if (!requiresRecipient(params)) {
708
+ throw new Error("V2 Router requires recipient parameters");
709
+ }
710
+ return await this.quote({
711
+ ...params,
712
+ recipient: depositAddress
713
+ });
714
+ }
715
+ /**
716
+ * Execute swap with V2 Router
717
+ * Automatically fetches final quote using receiveUser (depositAddress) to ensure correct routerMsg and signature.
718
+ */
719
+ async executeSwap(params) {
720
+ try {
721
+ if (!requiresRecipientInExecute(params)) {
722
+ return {
723
+ success: false,
724
+ error: "V2 Router requires sender and receiveUser parameters"
725
+ };
726
+ }
727
+ const { quote, sender, receiveUser } = params;
728
+ if (!quote.success) {
729
+ return {
730
+ success: false,
731
+ error: "Invalid quote"
732
+ };
733
+ }
734
+ if (!receiveUser || receiveUser.trim() === "") {
735
+ return {
736
+ success: false,
737
+ error: "receiveUser (depositAddress) is required"
738
+ };
739
+ }
740
+ if (receiveUser.startsWith("0x") && receiveUser.length === 42) {
741
+ return {
742
+ success: false,
743
+ 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)`
744
+ };
745
+ }
746
+ logger.debug("AggregateDexRouter - executeSwap params:", {
747
+ sender,
748
+ receiveUser,
749
+ tokenIn: quote.tokenIn.address,
750
+ tokenOut: quote.tokenOut.address,
751
+ amountIn: quote.amountIn,
752
+ tokens: quote.tokens,
753
+ dexs: quote.dexs
754
+ });
755
+ const slippage = quote.slippage || 5e-3;
756
+ const finalQuoteParams = {
757
+ tokenIn: quote.tokenIn,
758
+ tokenOut: quote.tokenOut,
759
+ amountIn: quote.amountIn,
760
+ slippage,
761
+ sender,
762
+ recipient: receiveUser
763
+ };
764
+ let finalQuote;
765
+ try {
766
+ finalQuote = await this.quote(finalQuoteParams);
767
+ if (!finalQuote.success) {
768
+ return {
769
+ success: false,
770
+ error: `Failed to fetch quote with receiveUser="${receiveUser}": ${finalQuote.error}`
771
+ };
772
+ }
773
+ } catch (error) {
774
+ logger.error("AggregateDexRouter - Failed to fetch quote with receiveUser:", error);
775
+ return {
776
+ success: false,
777
+ error: `Failed to fetch quote with receiveUser="${receiveUser}": ${error?.message || "Unknown error"}`
778
+ };
779
+ }
780
+ const routerMsg = finalQuote.routerMsg;
781
+ const signature = finalQuote.signature;
782
+ if (!routerMsg || !signature) {
783
+ return {
784
+ success: false,
785
+ error: `Quote fetched with receiveUser="${receiveUser}" is missing routerMsg or signature.`
786
+ };
787
+ }
788
+ logger.debug("AggregateDexRouter - Successfully fetched final quote:", {
789
+ receiveUser,
790
+ quoteRecipient: finalQuote.recipient,
791
+ routerMsgLength: routerMsg.length,
792
+ signatureLength: signature.length
793
+ });
794
+ const tokens = finalQuote.tokens || [];
795
+ const dexs = finalQuote.dexs || [];
796
+ const transactions = [];
797
+ const getStorageBalance = async (tokenId, accountId) => {
798
+ try {
799
+ return await this.nearChainAdapter.view({
800
+ contractId: tokenId,
801
+ methodName: "storage_balance_of",
802
+ args: { account_id: accountId }
803
+ });
804
+ } catch (error) {
805
+ return null;
806
+ }
807
+ };
808
+ const isNativeNear = finalQuote.tokenIn.symbol === "NEAR" || finalQuote.tokenIn.address === "near" || !finalQuote.tokenIn.address && finalQuote.tokenIn.symbol === "NEAR";
809
+ if (isNativeNear) {
810
+ const wrapNearStorageBalance = await getStorageBalance(
811
+ this.wrapNearContractId,
812
+ sender
813
+ ).catch(() => null);
814
+ if (!wrapNearStorageBalance) {
815
+ transactions.push({
816
+ contractId: this.wrapNearContractId,
817
+ methodName: "storage_deposit",
818
+ args: {
819
+ account_id: sender,
820
+ registration_only: true
821
+ },
822
+ gas: "50000000000000",
823
+ expandDeposit: this.NEW_ACCOUNT_STORAGE_COST
824
+ });
825
+ }
826
+ transactions.push({
827
+ contractId: this.wrapNearContractId,
828
+ methodName: "near_deposit",
829
+ args: {},
830
+ gas: "50000000000000",
831
+ expandDeposit: finalQuote.amountIn
832
+ });
833
+ }
834
+ const tokensToCheck = dexs.length > 1 ? tokens : [finalQuote.tokenOut.address];
835
+ const tokenStorageBalances = await Promise.all(
836
+ tokensToCheck.map(
837
+ (tokenId) => getStorageBalance(tokenId, sender).catch(() => null)
838
+ )
839
+ );
840
+ tokensToCheck.forEach((tokenId, index) => {
841
+ if (!tokenStorageBalances[index]) {
842
+ transactions.push({
843
+ contractId: tokenId,
844
+ methodName: "storage_deposit",
845
+ args: {
846
+ account_id: sender,
847
+ registration_only: true
848
+ },
849
+ gas: "50000000000000",
850
+ expandDeposit: this.NEW_ACCOUNT_STORAGE_COST
851
+ });
852
+ }
853
+ });
854
+ if (receiveUser && receiveUser !== sender) {
855
+ logger.debug("AggregateDexRouter - Checking receiveUser registration in tokenOut:", {
856
+ receiveUser,
857
+ tokenOut: finalQuote.tokenOut.address,
858
+ tokenOutSymbol: finalQuote.tokenOut.symbol
859
+ });
860
+ const receiveUserStorageBalance = await getStorageBalance(
861
+ finalQuote.tokenOut.address,
862
+ receiveUser
863
+ ).catch((error) => {
864
+ logger.warn("AggregateDexRouter - Failed to check receiveUser storage balance:", {
865
+ receiveUser,
866
+ tokenOut: finalQuote.tokenOut.address,
867
+ error: error?.message
868
+ });
869
+ return null;
870
+ });
871
+ if (!receiveUserStorageBalance) {
872
+ logger.debug("AggregateDexRouter - receiveUser not registered in tokenOut, adding registration transaction:", {
873
+ receiveUser,
874
+ tokenOut: finalQuote.tokenOut.address,
875
+ tokenOutSymbol: finalQuote.tokenOut.symbol,
876
+ storageCost: this.NEW_ACCOUNT_STORAGE_COST
877
+ });
878
+ transactions.push({
879
+ contractId: finalQuote.tokenOut.address,
880
+ methodName: "storage_deposit",
881
+ args: {
882
+ account_id: receiveUser,
883
+ registration_only: true
884
+ },
885
+ gas: "50000000000000",
886
+ expandDeposit: this.NEW_ACCOUNT_STORAGE_COST
887
+ });
888
+ }
889
+ }
890
+ const aggregateDexStorageBalances = await Promise.all(
891
+ tokens.map(
892
+ (tokenId) => getStorageBalance(tokenId, this.aggregateDexContractId).catch(
893
+ () => null
894
+ )
895
+ )
896
+ );
897
+ tokens.forEach((tokenId, index) => {
898
+ if (!aggregateDexStorageBalances[index]) {
899
+ transactions.push({
900
+ contractId: tokenId,
901
+ methodName: "storage_deposit",
902
+ args: {
903
+ account_id: this.aggregateDexContractId,
904
+ registration_only: true
905
+ },
906
+ gas: "50000000000000",
907
+ expandDeposit: this.NEW_ACCOUNT_STORAGE_COST
908
+ });
909
+ }
910
+ });
911
+ if (tokens.length > 0) {
912
+ const registeredStatus = await this.queryUserTokensRegistered({
913
+ user: sender,
914
+ tokens
915
+ });
916
+ const unregisteredTokens = tokens.filter(
917
+ (_, index) => !registeredStatus[index]
918
+ );
919
+ if (unregisteredTokens.length > 0) {
920
+ const depositPerToken = new Big2__default.default("0.005").mul(
921
+ new Big2__default.default("1000000000000000000000000")
922
+ );
923
+ const totalDeposit2 = depositPerToken.mul(unregisteredTokens.length);
924
+ transactions.push({
925
+ contractId: this.aggregateDexContractId,
926
+ methodName: "tokens_storage_deposit",
927
+ args: {
928
+ user: sender,
929
+ tokens: unregisteredTokens
930
+ },
931
+ gas: "30000000000000",
932
+ expandDeposit: totalDeposit2.toFixed(0)
933
+ });
934
+ }
935
+ }
936
+ const msgString = JSON.stringify({
937
+ msg: routerMsg,
938
+ signature
939
+ });
940
+ transactions.push({
941
+ contractId: finalQuote.tokenIn.address,
942
+ methodName: "ft_transfer_call",
943
+ args: {
944
+ receiver_id: this.aggregateDexContractId,
945
+ amount: finalQuote.amountIn,
946
+ msg: msgString
947
+ },
948
+ gas: "300000000000000",
949
+ expandDeposit: this.ONE_YOCTO_NEAR
950
+ });
951
+ const totalDeposit = transactions.reduce((sum, tx) => {
952
+ if (tx.expandDeposit) {
953
+ return sum.plus(tx.expandDeposit);
954
+ }
955
+ return sum;
956
+ }, new Big2__default.default(0));
957
+ logger.debug("AggregateDexRouter - Executing swap (following mature codebase logic):", {
958
+ contractId: finalQuote.tokenIn.address,
959
+ receiver_id: this.aggregateDexContractId,
960
+ amount: finalQuote.amountIn,
961
+ transactionsCount: transactions.length,
962
+ sender,
963
+ receiveUser,
964
+ tokens: tokens.length,
965
+ dexs: dexs.length,
966
+ totalDepositYocto: totalDeposit.toFixed(0),
967
+ totalDepositNEAR: totalDeposit.div(new Big2__default.default("1000000000000000000000000")).toFixed(6),
968
+ transactions: transactions.map((tx, idx) => ({
969
+ index: idx,
970
+ contractId: tx.contractId,
971
+ methodName: tx.methodName,
972
+ expandDeposit: tx.expandDeposit,
973
+ expandDepositNEAR: tx.expandDeposit ? new Big2__default.default(tx.expandDeposit).div(new Big2__default.default("1000000000000000000000000")).toFixed(6) : "0"
974
+ }))
975
+ });
976
+ const result = await this.nearChainAdapter.call({
977
+ transactions
978
+ });
979
+ if (result.status === "success") {
980
+ return {
981
+ success: true,
982
+ txHash: result.txHash,
983
+ txHashArray: result.txHashArr || (result.txHash ? [result.txHash] : [])
984
+ };
985
+ } else {
986
+ return {
987
+ success: false,
988
+ error: result.message || "Execute swap failed"
989
+ };
990
+ }
991
+ } catch (error) {
992
+ logger.error("AggregateDexRouter executeSwap - Error:", error);
993
+ return {
994
+ success: false,
995
+ error: error?.message || "Execute swap failed"
996
+ };
997
+ }
998
+ }
999
+ /**
1000
+ * Query user token registration status in AGGREGATE_DEX contract
1001
+ */
1002
+ async queryUserTokensRegistered({
1003
+ user,
1004
+ tokens
1005
+ }) {
1006
+ try {
1007
+ return await this.nearChainAdapter.view({
1008
+ contractId: this.aggregateDexContractId,
1009
+ methodName: "query_user_tokens_registered",
1010
+ args: {
1011
+ user,
1012
+ tokens
1013
+ }
1014
+ });
1015
+ } catch (error) {
1016
+ logger.error(
1017
+ "AggregateDexRouter - Failed to query user tokens registered:",
1018
+ error
1019
+ );
1020
+ return tokens.map(() => false);
1021
+ }
1022
+ }
1023
+ };
1024
+ async function completeQuote(params, config) {
1025
+ const {
1026
+ sourceToken,
1027
+ targetToken,
1028
+ sourceChain,
1029
+ targetChain: _targetChain,
1030
+ // Reserved for future use
1031
+ amountIn,
1032
+ slippage,
1033
+ recipient,
1034
+ refundTo
1035
+ } = params;
1036
+ const {
1037
+ intentsQuotationAdapter,
1038
+ dexRouters,
1039
+ dexRouter,
1040
+ bluechipTokens,
1041
+ configAdapter,
1042
+ currentUserAddress
1043
+ } = config;
1044
+ const wrapNearContractId = configAdapter.getWrapNearContractId();
1045
+ const routers = dexRouters || (dexRouter ? [dexRouter] : []);
1046
+ if (routers.length === 0) {
1047
+ throw new Error("At least one DEX router is required");
1048
+ }
1049
+ const userAddress = currentUserAddress || recipient;
1050
+ if (!userAddress) {
1051
+ throw new Error("currentUserAddress or recipient is required for V2 Router");
1052
+ }
1053
+ if (!sourceToken?.address) {
1054
+ throw new Error("Source token address is required");
1055
+ }
1056
+ if (!targetToken?.address) {
1057
+ throw new Error("Target token address is required");
1058
+ }
1059
+ const needsPreSwap = sourceChain === "near" && !isNearIntentsSupportedToken(sourceToken, bluechipTokens);
1060
+ const bluechipToken = findBestBluechipToken(
1061
+ bluechipTokens,
1062
+ wrapNearContractId
1063
+ );
1064
+ if (!bluechipToken?.address) {
1065
+ logger.error("DEX Aggregator - Failed to find bluechip token:", {
1066
+ bluechipToken,
1067
+ bluechipTokens
1068
+ });
1069
+ throw new Error("Failed to find bluechip token address");
1070
+ }
1071
+ logger.debug("DEX Aggregator - Using bluechip token:", {
1072
+ address: bluechipToken.address,
1073
+ symbol: bluechipToken.symbol,
1074
+ decimals: bluechipToken.decimals
1075
+ });
1076
+ let preSwapQuote = null;
1077
+ let bestRouter = null;
1078
+ if (needsPreSwap) {
1079
+ if (!sourceToken?.address) {
1080
+ throw new Error("Source token address is required");
1081
+ }
1082
+ logger.debug("DEX Aggregator - Pre-swap quote params:", {
1083
+ tokenIn: {
1084
+ address: sourceToken.address,
1085
+ symbol: sourceToken.symbol
1086
+ },
1087
+ tokenOut: {
1088
+ address: bluechipToken.address,
1089
+ symbol: bluechipToken.symbol
1090
+ },
1091
+ amountIn,
1092
+ slippage,
1093
+ routersCount: routers.length,
1094
+ userAddress
1095
+ });
1096
+ const quotes = await Promise.allSettled(
1097
+ routers.map((router) => {
1098
+ const capabilities = router.getCapabilities();
1099
+ const quoteParams = capabilities.requiresRecipient ? {
1100
+ tokenIn: sourceToken,
1101
+ tokenOut: bluechipToken,
1102
+ amountIn,
1103
+ slippage,
1104
+ swapType: "EXACT_INPUT",
1105
+ sender: userAddress,
1106
+ recipient: userAddress
1107
+ } : {
1108
+ tokenIn: sourceToken,
1109
+ tokenOut: bluechipToken,
1110
+ amountIn,
1111
+ slippage,
1112
+ swapType: "EXACT_INPUT"
1113
+ };
1114
+ return router.quote(quoteParams);
1115
+ })
1116
+ );
1117
+ const validQuotes = quotes.filter(
1118
+ (r) => r.status === "fulfilled" && r.value.success
1119
+ ).map((r) => r.value);
1120
+ if (validQuotes.length === 0) {
1121
+ const errors = quotes.map((r, index) => {
1122
+ if (r.status === "rejected") {
1123
+ return `Router ${index}: ${r.reason}`;
1124
+ }
1125
+ if (r.status === "fulfilled" && !r.value.success) {
1126
+ return `Router ${index}: ${r.value.error}`;
1127
+ }
1128
+ return null;
1129
+ }).filter(Boolean);
1130
+ logger.error("DEX Aggregator - All router quotes failed:", errors);
1131
+ throw new Error(
1132
+ `All router quotes failed: ${errors.join("; ")}`
1133
+ );
1134
+ }
1135
+ const bestQuote = validQuotes.reduce((best, current) => {
1136
+ const bestAmount = new Big2__default.default(best.amountOut);
1137
+ const currentAmount = new Big2__default.default(current.amountOut);
1138
+ return currentAmount.gt(bestAmount) ? current : best;
1139
+ });
1140
+ const bestQuoteIndex = validQuotes.indexOf(bestQuote);
1141
+ bestRouter = routers[bestQuoteIndex];
1142
+ preSwapQuote = bestQuote;
1143
+ logger.debug("DEX Aggregator - Selected best router:", {
1144
+ routerIndex: bestQuoteIndex,
1145
+ amountOut: bestQuote.amountOut,
1146
+ routerType: bestRouter.getCapabilities().requiresRecipient ? "V2 (Recipient)" : "V1 (Simple)"
1147
+ });
1148
+ const preSwapAmountOut = preSwapQuote.amountOut;
1149
+ if (!preSwapAmountOut || new Big2__default.default(preSwapAmountOut).lte(0)) {
1150
+ logger.error("DEX Aggregator - Pre-swap amountOut is invalid:", {
1151
+ amountOut: preSwapAmountOut,
1152
+ tokenIn: sourceToken,
1153
+ tokenOut: bluechipToken
1154
+ });
1155
+ throw new Error(
1156
+ "Pre-swap returned invalid amount: amount is too small or zero"
1157
+ );
1158
+ }
1159
+ logger.debug("DEX Aggregator - Pre-swap quote success:", {
1160
+ amountOut: preSwapAmountOut,
1161
+ tokenOut: bluechipToken.symbol,
1162
+ decimals: bluechipToken.decimals
1163
+ });
1164
+ }
1165
+ let normalizedSourceAsset;
1166
+ if (needsPreSwap) {
1167
+ const bluechipKey = bluechipToken.symbol?.toUpperCase() === "WNEAR" ? "NEAR" : bluechipToken.symbol?.toUpperCase();
1168
+ const bluechipTokenConfig = bluechipKey && bluechipTokens[bluechipKey] || void 0;
1169
+ if (bluechipTokenConfig?.assetId) {
1170
+ normalizedSourceAsset = bluechipTokenConfig.assetId;
1171
+ logger.debug("Using bluechip token assetId for NearIntents:", {
1172
+ symbol: bluechipToken.symbol,
1173
+ assetId: normalizedSourceAsset,
1174
+ contractAddress: bluechipToken.address
1175
+ });
1176
+ } else {
1177
+ normalizedSourceAsset = `nep141:${bluechipToken.address}`;
1178
+ logger.warn(
1179
+ "Bluechip token assetId not found, using contractAddress with prefix:",
1180
+ {
1181
+ symbol: bluechipToken.symbol,
1182
+ normalizedSourceAsset
1183
+ }
1184
+ );
1185
+ }
1186
+ } else {
1187
+ if (sourceToken.symbol) {
1188
+ const sourceKey = sourceToken.symbol.toUpperCase();
1189
+ const sourceTokenConfig = bluechipTokens[sourceKey];
1190
+ if (sourceTokenConfig?.assetId) {
1191
+ normalizedSourceAsset = sourceTokenConfig.assetId;
1192
+ } else {
1193
+ normalizedSourceAsset = normalizeTokenId(
1194
+ sourceToken.address,
1195
+ wrapNearContractId
1196
+ );
1197
+ if (!normalizedSourceAsset.startsWith("nep141:")) {
1198
+ normalizedSourceAsset = `nep141:${normalizedSourceAsset}`;
1199
+ }
1200
+ }
1201
+ } else {
1202
+ normalizedSourceAsset = normalizeTokenId(
1203
+ sourceToken.address,
1204
+ wrapNearContractId
1205
+ );
1206
+ if (!normalizedSourceAsset.startsWith("nep141:")) {
1207
+ normalizedSourceAsset = `nep141:${normalizedSourceAsset}`;
1208
+ }
1209
+ }
1210
+ }
1211
+ let normalizedTargetAsset = targetToken.address;
1212
+ if (normalizedTargetAsset && !normalizedTargetAsset.startsWith("nep141:") && !normalizedTargetAsset.startsWith("nep245:") && normalizedTargetAsset.includes(".")) {
1213
+ normalizedTargetAsset = `nep141:${normalizeTokenId(
1214
+ normalizedTargetAsset,
1215
+ wrapNearContractId
1216
+ )}`;
1217
+ }
1218
+ normalizedTargetAsset = normalizeDestinationAsset(normalizedTargetAsset, wrapNearContractId) || normalizedTargetAsset;
1219
+ const slippageBps = convertSlippageToBasisPoints(slippage);
1220
+ const intentsAmount = needsPreSwap ? preSwapQuote.amountOut : amountIn;
1221
+ logger.debug("DEX Aggregator - Calling NearIntents quotation:", {
1222
+ originAsset: normalizedSourceAsset,
1223
+ destinationAsset: normalizedTargetAsset,
1224
+ amount: intentsAmount,
1225
+ needsPreSwap,
1226
+ preSwapAmountOut: needsPreSwap ? preSwapQuote.amountOut : void 0
1227
+ });
1228
+ const swapTypeForIntents = needsPreSwap ? "FLEX_INPUT" : void 0;
1229
+ logger.debug("DEX Aggregator - swapType for NearIntents:", {
1230
+ needsPreSwap,
1231
+ swapType: swapTypeForIntents || "EXACT_INPUT (default)"
1232
+ });
1233
+ const intentsQuote = await intentsQuotationAdapter.quote({
1234
+ originAsset: normalizedSourceAsset,
1235
+ destinationAsset: normalizedTargetAsset,
1236
+ amount: intentsAmount,
1237
+ refundTo: refundTo || recipient,
1238
+ recipient,
1239
+ slippageTolerance: slippageBps,
1240
+ swapType: swapTypeForIntents
1241
+ });
1242
+ logger.debug("DEX Aggregator - NearIntents quotation result:", {
1243
+ quoteStatus: intentsQuote.quoteStatus,
1244
+ message: intentsQuote.message,
1245
+ hasDepositAddress: !!intentsQuote.quoteSuccessResult?.quote?.depositAddress
1246
+ });
1247
+ if (intentsQuote.quoteStatus !== "success") {
1248
+ const errorMessage = intentsQuote.message || "Unknown error";
1249
+ logger.error("DEX Aggregator - NearIntents quote failed:", {
1250
+ error: errorMessage,
1251
+ originAsset: normalizedSourceAsset,
1252
+ destinationAsset: normalizedTargetAsset,
1253
+ amount: intentsAmount,
1254
+ needsPreSwap,
1255
+ preSwapAmountOut: needsPreSwap ? preSwapQuote.amountOut : void 0
1256
+ });
1257
+ throw new Error(`Intents quote failed: ${errorMessage}`);
1258
+ }
1259
+ const depositAddress = intentsQuote.quoteSuccessResult?.quote?.depositAddress || "";
1260
+ if (!depositAddress) {
1261
+ throw new Error("Deposit address not found in intents quote");
1262
+ }
1263
+ const finalQuote = preSwapQuote;
1264
+ return {
1265
+ intents: {
1266
+ quote: intentsQuote,
1267
+ depositAddress
1268
+ },
1269
+ preSwap: needsPreSwap && finalQuote && bestRouter ? {
1270
+ quote: finalQuote,
1271
+ tokenIn: sourceToken,
1272
+ tokenOut: bluechipToken,
1273
+ executor: bestRouter
1274
+ } : void 0,
1275
+ finalAmountOut: intentsQuote.quoteSuccessResult?.quote?.amountOut || "0"
1276
+ };
1277
+ }
1278
+
1279
+ exports.AggregateDexRouter = AggregateDexRouter;
1280
+ exports.NearSmartRouter = NearSmartRouter;
1281
+ exports.completeQuote = completeQuote;
1282
+ exports.convertSlippageToBasisPoints = convertSlippageToBasisPoints;
1283
+ exports.findBestBluechipToken = findBestBluechipToken;
1284
+ exports.formatGasString = formatGasString;
1285
+ exports.formatGasToTgas = formatGasToTgas;
1286
+ exports.getBluechipTokensConfig = getBluechipTokensConfig;
1287
+ exports.isNearIntentsSupportedToken = isNearIntentsSupportedToken;
1288
+ exports.logger = logger;
1289
+ exports.normalizeDestinationAsset = normalizeDestinationAsset;
1290
+ exports.normalizeTokenId = normalizeTokenId;
1291
+ exports.requiresRecipient = requiresRecipient;
1292
+ exports.requiresRecipientInExecute = requiresRecipientInExecute;
1293
+ exports.setBluechipTokensConfig = setBluechipTokensConfig;
1294
+ //# sourceMappingURL=index.js.map
1295
+ //# sourceMappingURL=index.js.map