@cowprotocol/sdk-bridging 0.3.3-beta.0 → 0.4.0

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
@@ -122,6 +122,93 @@ function isAppDoc(appData) {
122
122
  return typeof appData === "object" && appData !== null && "version" in appData && "metadata" in appData;
123
123
  }
124
124
 
125
+ // src/const.ts
126
+ var import_sdk_config = require("@cowprotocol/sdk-config");
127
+ var RAW_PROVIDERS_FILES_PATH = `${import_sdk_config.RAW_FILES_PATH}/src/bridging/providers`;
128
+ var DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION = 24e4;
129
+ var DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION = 2e5;
130
+ var COW_SHED_PROXY_CREATION_GAS = 36e4;
131
+ var DEFAULT_EXTRA_GAS_PROXY_CREATION = 4e5;
132
+ var HOOK_DAPP_BRIDGE_PROVIDER_PREFIX = "cow-sdk://bridging/providers";
133
+
134
+ // src/BridgingSdk/findBridgeProviderFromHook.ts
135
+ function findBridgeProviderFromHook(fullAppData, providers) {
136
+ const postHooks = getPostHooks(fullAppData);
137
+ const bridgingHook = postHooks.find((hook) => {
138
+ return hook.dappId?.startsWith(HOOK_DAPP_BRIDGE_PROVIDER_PREFIX);
139
+ });
140
+ if (!bridgingHook) {
141
+ return void 0;
142
+ }
143
+ const bridgeProviderDappId = bridgingHook.dappId;
144
+ return providers.find((provider) => provider.info.dappId === bridgeProviderDappId);
145
+ }
146
+
147
+ // src/BridgingSdk/getCrossChainOrder.ts
148
+ async function getCrossChainOrder(params) {
149
+ const { chainId, orderId, orderBookApi, providers, env } = params;
150
+ const chainContext = { chainId, env };
151
+ const order = await orderBookApi.getOrder(orderId, chainContext);
152
+ const provider = order.fullAppData && findBridgeProviderFromHook(order.fullAppData, providers);
153
+ if (!provider) {
154
+ throw new BridgeOrderParsingError(
155
+ `Unknown Bridge provider in order ${order.uid}. Add provider to the SDK config to be able to decode the order`
156
+ );
157
+ }
158
+ const trades = await orderBookApi.getTrades({ orderUid: order.uid }, chainContext);
159
+ if (trades.length > 0) {
160
+ const firstTrade = trades[0];
161
+ const tradeTxHash = firstTrade?.txHash;
162
+ if (!tradeTxHash) {
163
+ throw new BridgeOrderParsingError(
164
+ `No tx hash found for order ${orderId} . First trade, with log index ${firstTrade?.logIndex}`
165
+ );
166
+ }
167
+ const { params: bridgingParams, status: statusResult } = await provider.getBridgingParams(chainId, orderId, tradeTxHash) || {};
168
+ if (!bridgingParams || !statusResult) {
169
+ throw new BridgeOrderParsingError(`Bridging params cannot be derived from transaction: ${tradeTxHash}`);
170
+ }
171
+ const state = {
172
+ provider,
173
+ chainId,
174
+ order,
175
+ statusResult: {
176
+ status: "unknown" /* UNKNOWN */
177
+ },
178
+ bridgingParams,
179
+ tradeTxHash
180
+ };
181
+ try {
182
+ const explorerUrl = provider.getExplorerUrl(bridgingParams.bridgingId);
183
+ return {
184
+ ...state,
185
+ statusResult,
186
+ explorerUrl
187
+ };
188
+ } catch (e) {
189
+ console.error("Cannot get bridging status", e);
190
+ return state;
191
+ }
192
+ }
193
+ return null;
194
+ }
195
+
196
+ // src/BridgingSdk/BridgingSdk.ts
197
+ var import_sdk_trading2 = require("@cowprotocol/sdk-trading");
198
+ var import_sdk_order_book2 = require("@cowprotocol/sdk-order-book");
199
+ var import_sdk_config2 = require("@cowprotocol/sdk-config");
200
+ var import_sdk_common4 = require("@cowprotocol/sdk-common");
201
+
202
+ // src/BridgingSdk/helpers.ts
203
+ var getCacheKey = ({
204
+ id,
205
+ buyChainId,
206
+ sellChainId = "noSellChainID",
207
+ tokenAddress = "noTokenAddress"
208
+ }) => {
209
+ return `${id}-${buyChainId}-${sellChainId}-${tokenAddress.toLowerCase()}`;
210
+ };
211
+
125
212
  // src/BridgingSdk/getQuoteWithoutBridge.ts
126
213
  var import_sdk_common = require("@cowprotocol/sdk-common");
127
214
  function getQuoteWithoutBridge(params) {
@@ -141,6 +228,8 @@ function getQuoteWithoutBridge(params) {
141
228
 
142
229
  // src/BridgingSdk/getQuoteWithBridge.ts
143
230
  var import_sdk_trading = require("@cowprotocol/sdk-trading");
231
+ var import_sdk_common3 = require("@cowprotocol/sdk-common");
232
+ var import_sdk_order_book = require("@cowprotocol/sdk-order-book");
144
233
 
145
234
  // src/BridgingSdk/getBridgeSignedHook.ts
146
235
  var import_sdk_common2 = require("@cowprotocol/sdk-common");
@@ -168,19 +257,6 @@ async function getBridgeSignedHook(bridgeRequest, { provider, signer, hookGasLim
168
257
  };
169
258
  }
170
259
 
171
- // src/const.ts
172
- var import_sdk_config = require("@cowprotocol/sdk-config");
173
- var RAW_PROVIDERS_FILES_PATH = `${import_sdk_config.RAW_FILES_PATH}/src/bridging/providers`;
174
- var DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION = 24e4;
175
- var DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION = 2e5;
176
- var COW_SHED_PROXY_CREATION_GAS = 36e4;
177
- var DEFAULT_EXTRA_GAS_PROXY_CREATION = 4e5;
178
- var HOOK_DAPP_BRIDGE_PROVIDER_PREFIX = "cow-sdk://bridging/providers";
179
-
180
- // src/BridgingSdk/getQuoteWithBridge.ts
181
- var import_sdk_order_book = require("@cowprotocol/sdk-order-book");
182
- var import_sdk_common3 = require("@cowprotocol/sdk-common");
183
-
184
260
  // src/hooks/utils.ts
185
261
  function getHookMockForCostEstimation(gasLimit) {
186
262
  return {
@@ -214,7 +290,8 @@ async function getQuoteWithBridge(params) {
214
290
  );
215
291
  const bridgeRequestWithoutAmount = await getBaseBridgeQuoteRequest({
216
292
  swapAndBridgeRequest,
217
- provider
293
+ provider,
294
+ intermediateTokensCache: params.intermediateTokensCache
218
295
  });
219
296
  const hookEstimatedGasLimit = await provider.getGasLimitEstimationForHook(bridgeRequestWithoutAmount);
220
297
  const mockedHook = getHookMockForCostEstimation(hookEstimatedGasLimit);
@@ -256,7 +333,7 @@ async function getQuoteWithBridge(params) {
256
333
  });
257
334
  const intermediateTokenAmount = swapResult.amountsAndCosts.afterSlippage.buyAmount;
258
335
  (0, import_sdk_common3.log)(
259
- `Expected to receive ${intermediateTokenAmount} of the intermediate token (${(intermediateTokenAmount / BigInt(10 ** intermediaryTokenDecimals)).toString()} formatted)`
336
+ `Expected to receive ${intermediateTokenAmount} of the intermediate token (${(intermediateTokenAmount / 10n ** BigInt(intermediaryTokenDecimals)).toString()} formatted)`
260
337
  );
261
338
  async function signHooksAndSetSwapResult(signer2, hookGasLimit, advancedSettings2) {
262
339
  const appDataOverride = advancedSettings2?.appData;
@@ -350,13 +427,26 @@ async function getQuoteWithBridge(params) {
350
427
  };
351
428
  }
352
429
  async function getBaseBridgeQuoteRequest(params) {
353
- const { provider, swapAndBridgeRequest: quoteBridgeRequest } = params;
354
- const intermediateTokens = await provider.getIntermediateTokens(quoteBridgeRequest);
430
+ const { provider, swapAndBridgeRequest: quoteBridgeRequest, intermediateTokensCache } = params;
431
+ let intermediateTokens = [];
432
+ const cacheKey = getCacheKey({
433
+ id: provider.info.dappId,
434
+ buyChainId: quoteBridgeRequest.buyTokenChainId.toString(),
435
+ sellChainId: quoteBridgeRequest.sellTokenChainId.toString(),
436
+ tokenAddress: quoteBridgeRequest.buyTokenAddress
437
+ });
438
+ const cached = intermediateTokensCache?.get(cacheKey);
439
+ if (cached) {
440
+ intermediateTokens = cached;
441
+ } else {
442
+ intermediateTokens = await provider.getIntermediateTokens(quoteBridgeRequest);
443
+ intermediateTokensCache?.set(cacheKey, intermediateTokens);
444
+ }
355
445
  if (intermediateTokens.length === 0) {
356
446
  throw new BridgeProviderQuoteError("NO_INTERMEDIATE_TOKENS" /* NO_INTERMEDIATE_TOKENS */);
357
447
  }
358
448
  const intermediateToken = intermediateTokens[0];
359
- (0, import_sdk_common3.log)(`Using ${intermediateToken} as intermediate tokens`);
449
+ (0, import_sdk_common3.log)(`Using ${intermediateToken?.name ?? intermediateToken?.address} as intermediate tokens`);
360
450
  if (!intermediateToken) {
361
451
  throw new BridgeProviderQuoteError("NO_INTERMEDIATE_TOKENS" /* NO_INTERMEDIATE_TOKENS */, { intermediateTokens });
362
452
  }
@@ -404,82 +494,333 @@ async function getBridgeResult(context) {
404
494
  return { bridgeResult, bridgeHook, appDataInfo };
405
495
  }
406
496
 
407
- // src/BridgingSdk/findBridgeProviderFromHook.ts
408
- function findBridgeProviderFromHook(fullAppData, providers) {
409
- const postHooks = getPostHooks(fullAppData);
410
- const bridgingHook = postHooks.find((hook) => {
411
- return hook.dappId?.startsWith(HOOK_DAPP_BRIDGE_PROVIDER_PREFIX);
412
- });
413
- if (!bridgingHook) {
414
- return void 0;
497
+ // src/BridgingSdk/strategies/QuoteStrategy.ts
498
+ var QuoteStrategy = class {
499
+ constructor(intermediateTokensCache) {
500
+ this.intermediateTokensCache = intermediateTokensCache;
415
501
  }
416
- const bridgeProviderDappId = bridgingHook.dappId;
417
- return providers.find((provider) => provider.info.dappId === bridgeProviderDappId);
418
- }
502
+ };
503
+ var BaseSingleQuoteStrategy = class extends QuoteStrategy {
504
+ };
505
+ var BaseMultiQuoteStrategy = class extends QuoteStrategy {
506
+ };
507
+ var BaseBestQuoteStrategy = class extends QuoteStrategy {
508
+ };
419
509
 
420
- // src/BridgingSdk/getCrossChainOrder.ts
421
- async function getCrossChainOrder(params) {
422
- const { chainId, orderId, orderBookApi, providers, env } = params;
423
- const chainContext = { chainId, env };
424
- const order = await orderBookApi.getOrder(orderId, chainContext);
425
- const provider = order.fullAppData && findBridgeProviderFromHook(order.fullAppData, providers);
426
- if (!provider) {
427
- throw new BridgeOrderParsingError(
428
- `Unknown Bridge provider in order ${order.uid}. Add provider to the SDK config to be able to decode the order`
510
+ // src/BridgingSdk/strategies/SingleQuoteStrategy.ts
511
+ var SingleQuoteStrategy = class extends BaseSingleQuoteStrategy {
512
+ strategyName = "SingleQuoteStrategy";
513
+ constructor(intermediateTokensCache) {
514
+ super(intermediateTokensCache);
515
+ }
516
+ async execute(request, config) {
517
+ const { quoteBridgeRequest, advancedSettings } = request;
518
+ const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
519
+ const { tradingSdk, providers } = config;
520
+ if (sellTokenChainId !== buyTokenChainId) {
521
+ const provider = providers[0];
522
+ if (!provider) {
523
+ throw new Error("No provider found for cross-chain swap");
524
+ }
525
+ const baseParams = {
526
+ swapAndBridgeRequest: quoteBridgeRequest,
527
+ advancedSettings,
528
+ tradingSdk,
529
+ provider,
530
+ bridgeHookSigner: advancedSettings?.quoteSigner
531
+ };
532
+ const request2 = this.intermediateTokensCache ? {
533
+ ...baseParams,
534
+ intermediateTokensCache: this.intermediateTokensCache
535
+ } : baseParams;
536
+ return getQuoteWithBridge(request2);
537
+ } else {
538
+ return getQuoteWithoutBridge({
539
+ quoteBridgeRequest,
540
+ advancedSettings,
541
+ tradingSdk
542
+ });
543
+ }
544
+ }
545
+ };
546
+
547
+ // src/BridgingSdk/utils.ts
548
+ function validateCrossChainRequest(sellTokenChainId, buyTokenChainId) {
549
+ if (sellTokenChainId === buyTokenChainId) {
550
+ throw new BridgeProviderError(
551
+ "getMultiQuotes() and getBestQuote() are only for cross-chain bridging. For single-chain swaps, use getQuote() instead.",
552
+ { sellTokenChainId, buyTokenChainId }
429
553
  );
430
554
  }
431
- const trades = await orderBookApi.getTrades({ orderUid: order.uid }, chainContext);
432
- if (trades.length > 0) {
433
- const firstTrade = trades[0];
434
- const tradeTxHash = firstTrade?.txHash;
435
- if (!tradeTxHash) {
436
- throw new BridgeOrderParsingError(
437
- `No tx hash found for order ${orderId} . First trade, with log index ${firstTrade?.logIndex}`
555
+ }
556
+ function createBridgeQuoteTimeoutPromise(timeoutMs, prefix) {
557
+ return new Promise((_, reject) => {
558
+ setTimeout(() => {
559
+ reject(new BridgeProviderError(`${prefix} timeout after ${timeoutMs}ms`, {}));
560
+ }, timeoutMs);
561
+ });
562
+ }
563
+ function safeCallProgressiveCallback(onQuoteResult, result) {
564
+ if (!onQuoteResult) {
565
+ return;
566
+ }
567
+ try {
568
+ onQuoteResult(result);
569
+ } catch (callbackError) {
570
+ console.warn("Error in onQuoteResult callback:", callbackError);
571
+ }
572
+ }
573
+ function fillTimeoutResults(results, providersToQuery) {
574
+ for (let i = 0; i < providersToQuery.length; i++) {
575
+ const provider = providersToQuery[i];
576
+ if (!results[i] && provider) {
577
+ results[i] = {
578
+ providerDappId: provider.info.dappId,
579
+ quote: null,
580
+ error: new BridgeProviderError("Provider request timed out", {})
581
+ };
582
+ }
583
+ }
584
+ }
585
+ async function executeProviderQuotes(promises, timeout, config) {
586
+ try {
587
+ await Promise.race([
588
+ Promise.allSettled(promises),
589
+ createBridgeQuoteTimeoutPromise(timeout, `Multi-quote with ${config.providers.length}`)
590
+ ]);
591
+ } catch {
592
+ console.warn("getMultiQuotes timeout occurred, returning partial results");
593
+ }
594
+ }
595
+ function isBetterQuote(quote1, quote2) {
596
+ if (!quote2 || !quote2.quote) {
597
+ return !!quote1.quote;
598
+ }
599
+ if (!quote1.quote) {
600
+ return false;
601
+ }
602
+ const quote1BuyAmount = quote1.quote.bridge.amountsAndCosts.afterSlippage.buyAmount;
603
+ const quote2BuyAmount = quote2.quote.bridge.amountsAndCosts.afterSlippage.buyAmount;
604
+ return quote1BuyAmount > quote2BuyAmount;
605
+ }
606
+ function safeCallBestQuoteCallback(onQuoteResult, result) {
607
+ if (!onQuoteResult) {
608
+ return;
609
+ }
610
+ try {
611
+ onQuoteResult(result);
612
+ } catch (callbackError) {
613
+ console.warn("Error in onQuoteResult callback:", callbackError);
614
+ }
615
+ }
616
+ function resolveProvidersToQuery(providerDappIds, providers) {
617
+ if (!providerDappIds) {
618
+ return providers;
619
+ }
620
+ return providerDappIds.map((dappId) => {
621
+ const provider = providers.find((p) => p.info.dappId === dappId);
622
+ if (!provider) {
623
+ throw new BridgeProviderError(
624
+ `Provider with dappId '${dappId}' not found. Available providers: ${providers.map((p) => p.info.dappId).join(", ")}`,
625
+ { providers }
438
626
  );
439
627
  }
440
- const { params: bridgingParams, status: statusResult } = await provider.getBridgingParams(chainId, orderId, tradeTxHash) || {};
441
- if (!bridgingParams || !statusResult) {
442
- throw new BridgeOrderParsingError(`Bridging params cannot be derived from transaction: ${tradeTxHash}`);
628
+ return provider;
629
+ });
630
+ }
631
+
632
+ // src/BridgingSdk/strategies/MultiQuoteStrategy.ts
633
+ var DEFAULT_TOTAL_TIMEOUT_MS = 4e4;
634
+ var DEFAULT_PROVIDER_TIMEOUT_MS = 2e4;
635
+ var MultiQuoteStrategy = class extends BaseMultiQuoteStrategy {
636
+ strategyName = "MultiQuoteStrategy";
637
+ constructor(intermediateTokensCache) {
638
+ super(intermediateTokensCache);
639
+ }
640
+ async execute(request, config) {
641
+ const { quoteBridgeRequest, providerDappIds, advancedSettings, options } = request;
642
+ const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
643
+ validateCrossChainRequest(sellTokenChainId, buyTokenChainId);
644
+ const providersToQuery = resolveProvidersToQuery(providerDappIds, config.providers);
645
+ const {
646
+ onQuoteResult,
647
+ totalTimeout = DEFAULT_TOTAL_TIMEOUT_MS,
648
+ providerTimeout = DEFAULT_PROVIDER_TIMEOUT_MS
649
+ } = options || {};
650
+ const results = [];
651
+ const promises = [];
652
+ for (let i = 0; i < providersToQuery.length; i++) {
653
+ const provider = providersToQuery[i];
654
+ if (!provider) {
655
+ continue;
656
+ }
657
+ const context = {
658
+ provider,
659
+ quoteBridgeRequest,
660
+ advancedSettings,
661
+ providerTimeout,
662
+ onQuoteResult,
663
+ results,
664
+ index: i
665
+ };
666
+ const promise = this.createProviderQuotePromise(context, config);
667
+ promises.push(promise);
443
668
  }
444
- const state = {
445
- provider,
446
- chainId,
447
- order,
448
- statusResult: {
449
- status: "unknown" /* UNKNOWN */
450
- },
451
- bridgingParams,
452
- tradeTxHash
453
- };
454
- try {
455
- const explorerUrl = provider.getExplorerUrl(bridgingParams.bridgingId);
456
- return {
457
- ...state,
458
- statusResult,
459
- explorerUrl
669
+ await executeProviderQuotes(promises, totalTimeout, config);
670
+ fillTimeoutResults(results, providersToQuery);
671
+ results.sort((a, b) => {
672
+ if (isBetterQuote(a, b))
673
+ return -1;
674
+ if (isBetterQuote(b, a))
675
+ return 1;
676
+ return 0;
677
+ });
678
+ return results;
679
+ }
680
+ createProviderQuotePromise(context, config) {
681
+ const { provider, quoteBridgeRequest, advancedSettings, providerTimeout, onQuoteResult, results, index } = context;
682
+ return (async () => {
683
+ try {
684
+ const baseParams = {
685
+ swapAndBridgeRequest: quoteBridgeRequest,
686
+ advancedSettings,
687
+ tradingSdk: config.tradingSdk,
688
+ provider,
689
+ bridgeHookSigner: advancedSettings?.quoteSigner
690
+ };
691
+ const request = this.intermediateTokensCache ? {
692
+ ...baseParams,
693
+ intermediateTokensCache: this.intermediateTokensCache
694
+ } : baseParams;
695
+ const quote = await Promise.race([
696
+ getQuoteWithBridge(request),
697
+ createBridgeQuoteTimeoutPromise(providerTimeout, `Provider ${provider.info.dappId}`)
698
+ ]);
699
+ const result = {
700
+ providerDappId: provider.info.dappId,
701
+ quote,
702
+ error: void 0
703
+ };
704
+ results[index] = result;
705
+ safeCallProgressiveCallback(onQuoteResult, result);
706
+ } catch (error) {
707
+ const result = {
708
+ providerDappId: provider.info.dappId,
709
+ quote: null,
710
+ error: error instanceof Error ? error : new BridgeProviderError(String(error), {})
711
+ };
712
+ results[index] = result;
713
+ safeCallProgressiveCallback(onQuoteResult, result);
714
+ }
715
+ })();
716
+ }
717
+ };
718
+
719
+ // src/BridgingSdk/strategies/BestQuoteStrategy.ts
720
+ var DEFAULT_TOTAL_TIMEOUT_MS2 = 4e4;
721
+ var DEFAULT_PROVIDER_TIMEOUT_MS2 = 2e4;
722
+ var BestQuoteStrategy = class extends BaseBestQuoteStrategy {
723
+ strategyName = "BestQuoteStrategy";
724
+ constructor(intermediateTokensCache) {
725
+ super(intermediateTokensCache);
726
+ }
727
+ async execute(request, config) {
728
+ const { quoteBridgeRequest, providerDappIds, advancedSettings, options } = request;
729
+ const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
730
+ validateCrossChainRequest(sellTokenChainId, buyTokenChainId);
731
+ const providersToQuery = resolveProvidersToQuery(providerDappIds, config.providers);
732
+ const {
733
+ onQuoteResult,
734
+ totalTimeout = DEFAULT_TOTAL_TIMEOUT_MS2,
735
+ providerTimeout = DEFAULT_PROVIDER_TIMEOUT_MS2
736
+ } = options || {};
737
+ const bestResult = { current: null };
738
+ const firstError = { current: null };
739
+ const promises = [];
740
+ for (const provider of providersToQuery) {
741
+ const context = {
742
+ provider,
743
+ quoteBridgeRequest,
744
+ advancedSettings,
745
+ providerTimeout,
746
+ onQuoteResult,
747
+ bestResult,
748
+ firstError
460
749
  };
461
- } catch (e) {
462
- console.error("Cannot get bridging status", e);
463
- return state;
750
+ const promise = this.createBestQuoteProviderPromise(context, config);
751
+ promises.push(promise);
464
752
  }
753
+ await executeProviderQuotes(promises, totalTimeout, config);
754
+ return bestResult.current || firstError.current;
465
755
  }
466
- return null;
756
+ createBestQuoteProviderPromise(context, config) {
757
+ const { provider, quoteBridgeRequest, advancedSettings, providerTimeout, onQuoteResult, bestResult, firstError } = context;
758
+ return (async () => {
759
+ try {
760
+ const baseParams = {
761
+ swapAndBridgeRequest: quoteBridgeRequest,
762
+ advancedSettings,
763
+ tradingSdk: config.tradingSdk,
764
+ provider,
765
+ bridgeHookSigner: advancedSettings?.quoteSigner
766
+ };
767
+ const request = this.intermediateTokensCache ? {
768
+ ...baseParams,
769
+ intermediateTokensCache: this.intermediateTokensCache
770
+ } : baseParams;
771
+ const quote = await Promise.race([
772
+ getQuoteWithBridge(request),
773
+ createBridgeQuoteTimeoutPromise(providerTimeout, `Provider ${provider.info.dappId}`)
774
+ ]);
775
+ const result = {
776
+ providerDappId: provider.info.dappId,
777
+ quote,
778
+ error: void 0
779
+ };
780
+ if (isBetterQuote(result, bestResult.current)) {
781
+ bestResult.current = result;
782
+ safeCallBestQuoteCallback(onQuoteResult, result);
783
+ }
784
+ } catch (error) {
785
+ const errorResult = {
786
+ providerDappId: provider.info.dappId,
787
+ quote: null,
788
+ error: error instanceof Error ? error : new BridgeProviderError(String(error), {})
789
+ };
790
+ if (!firstError.current) {
791
+ firstError.current = errorResult;
792
+ }
793
+ }
794
+ })();
795
+ }
796
+ };
797
+
798
+ // src/BridgingSdk/strategies/createStrategies.ts
799
+ function createStrategies(intermediateTokensCache) {
800
+ return {
801
+ singleQuoteStrategy: new SingleQuoteStrategy(intermediateTokensCache),
802
+ multiQuoteStrategy: new MultiQuoteStrategy(intermediateTokensCache),
803
+ bestQuoteStrategy: new BestQuoteStrategy(intermediateTokensCache)
804
+ };
467
805
  }
468
806
 
469
807
  // src/BridgingSdk/BridgingSdk.ts
470
- var import_sdk_trading2 = require("@cowprotocol/sdk-trading");
471
- var import_sdk_order_book2 = require("@cowprotocol/sdk-order-book");
472
- var import_sdk_config2 = require("@cowprotocol/sdk-config");
473
- var import_sdk_common4 = require("@cowprotocol/sdk-common");
808
+ var DEFAULT_CACHE_CONFIG = {
809
+ enabled: true,
810
+ intermediateTokensTtl: 5 * 60 * 1e3,
811
+ // 5 minutes
812
+ buyTokensTtl: 2 * 60 * 1e3
813
+ // 2 minutes
814
+ };
474
815
  var BridgingSdk = class {
475
816
  constructor(options, adapter) {
476
817
  this.options = options;
477
818
  if (adapter) {
478
819
  (0, import_sdk_common4.setGlobalAdapter)(adapter);
479
820
  }
480
- const { providers, ...restOptions } = options;
481
- if (!providers || providers.length !== 1) {
482
- throw new Error("Current implementation only supports a single bridge provider");
821
+ const { providers, cacheConfig, ...restOptions } = options;
822
+ if (!providers || providers.length === 0) {
823
+ throw new Error("At least one bridge provider is required");
483
824
  }
484
825
  if (options.enableLogging !== void 0) {
485
826
  (0, import_sdk_common4.enableLogging)(options.enableLogging);
@@ -492,8 +833,31 @@ var BridgingSdk = class {
492
833
  tradingSdk,
493
834
  orderBookApi
494
835
  };
836
+ this.cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig };
837
+ this.intermediateTokensCache = new import_sdk_common4.TTLCache(
838
+ "bridging-intermediate-tokens",
839
+ this.cacheConfig.enabled,
840
+ this.cacheConfig.intermediateTokensTtl
841
+ );
842
+ this.buyTokensCache = new import_sdk_common4.TTLCache(
843
+ "bridging-buy-tokens",
844
+ this.cacheConfig.enabled,
845
+ this.cacheConfig.buyTokensTtl
846
+ );
847
+ const { singleQuoteStrategy, multiQuoteStrategy, bestQuoteStrategy } = createStrategies(
848
+ this.cacheConfig.enabled ? this.intermediateTokensCache : void 0
849
+ );
850
+ this.singleQuoteStrategy = singleQuoteStrategy;
851
+ this.multiQuoteStrategy = multiQuoteStrategy;
852
+ this.bestQuoteStrategy = bestQuoteStrategy;
495
853
  }
496
854
  config;
855
+ cacheConfig;
856
+ intermediateTokensCache;
857
+ buyTokensCache;
858
+ singleQuoteStrategy;
859
+ multiQuoteStrategy;
860
+ bestQuoteStrategy;
497
861
  get provider() {
498
862
  const { providers } = this.config;
499
863
  if (!providers[0]) {
@@ -525,7 +889,22 @@ var BridgingSdk = class {
525
889
  * @param params
526
890
  */
527
891
  async getBuyTokens(params) {
528
- return this.provider.getBuyTokens(params);
892
+ const providerId = this.provider.info.dappId;
893
+ const cacheKey = getCacheKey({
894
+ id: providerId,
895
+ buyChainId: params.buyChainId.toString(),
896
+ sellChainId: params.sellChainId?.toString(),
897
+ tokenAddress: params.sellTokenAddress
898
+ });
899
+ const cached = this.cacheConfig.enabled && this.buyTokensCache.get(cacheKey);
900
+ if (cached) {
901
+ return cached;
902
+ }
903
+ const result = await this.provider.getBuyTokens(params);
904
+ if (this.cacheConfig.enabled) {
905
+ this.buyTokensCache.set(cacheKey, result);
906
+ }
907
+ return result;
529
908
  }
530
909
  /**
531
910
  * Get quote details, including a callback function to post the order on-chain.
@@ -543,23 +922,49 @@ var BridgingSdk = class {
543
922
  * @throws Error if no path is found
544
923
  */
545
924
  async getQuote(quoteBridgeRequest, advancedSettings) {
546
- const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
547
- const tradingSdk = this.config.tradingSdk;
548
- if (sellTokenChainId !== buyTokenChainId) {
549
- return getQuoteWithBridge({
550
- swapAndBridgeRequest: quoteBridgeRequest,
551
- advancedSettings,
552
- tradingSdk,
553
- provider: this.provider,
554
- bridgeHookSigner: advancedSettings?.quoteSigner
555
- });
556
- } else {
557
- return getQuoteWithoutBridge({
925
+ return this.singleQuoteStrategy.execute(
926
+ {
558
927
  quoteBridgeRequest,
559
- advancedSettings,
560
- tradingSdk
561
- });
562
- }
928
+ advancedSettings
929
+ },
930
+ this.config
931
+ );
932
+ }
933
+ /**
934
+ * Get quotes from multiple bridge providers in parallel with progressive results.
935
+ *
936
+ * This method is specifically for cross-chain bridging quotes. For single-chain swaps, use getQuote() instead.
937
+ *
938
+ * Features:
939
+ * - Progressive results: Use the `onQuoteResult` callback to receive quotes as soon as each provider responds
940
+ * - Timeout support: Configure maximum wait time for all providers and individual provider timeouts
941
+ * - Parallel execution: All providers are queried simultaneously for best performance
942
+ *
943
+ * @param request - The multi-quote request containing quote parameters, provider dappIds, and options
944
+ * @returns Array of results, one for each provider (successful quotes or errors)
945
+ * @throws Error if the request is for a single-chain swap (sellTokenChainId === buyTokenChainId)
946
+ * ```
947
+ */
948
+ async getMultiQuotes(request) {
949
+ return this.multiQuoteStrategy.execute(request, this.config);
950
+ }
951
+ /**
952
+ * Get the best quote from multiple bridge providers with progressive updates.
953
+ *
954
+ * This method is specifically for cross-chain bridging quotes. For single-chain swaps, use getQuote() instead.
955
+ *
956
+ * Features:
957
+ * - Returns only the best quote based on buyAmount after slippage
958
+ * - Progressive updates: Use the `onQuoteResult` callback to receive updates whenever a better quote is found
959
+ * - Timeout support: Configure maximum wait time for all providers and individual provider timeouts
960
+ * - Parallel execution: All providers are queried simultaneously for best performance
961
+ *
962
+ * @param request - The best quote request containing quote parameters, provider dappIds, and options
963
+ * @returns The best quote result found, or null if no successful quotes were obtained
964
+ * @throws Error if the request is for a single-chain swap (sellTokenChainId === buyTokenChainId)
965
+ */
966
+ async getBestQuote(request) {
967
+ return this.bestQuoteStrategy.execute(request, this.config);
563
968
  }
564
969
  async getOrder(params) {
565
970
  const { orderBookApi } = this.config;
@@ -578,6 +983,32 @@ var BridgingSdk = class {
578
983
  getProviderFromAppData(fullAppData) {
579
984
  return findBridgeProviderFromHook(fullAppData, this.getProviders());
580
985
  }
986
+ /**
987
+ * Clear all caches. Useful for testing and debugging.
988
+ */
989
+ clearCache() {
990
+ this.intermediateTokensCache.clear();
991
+ this.buyTokensCache.clear();
992
+ }
993
+ /**
994
+ * Clean up expired cache entries. Useful for maintenance.
995
+ */
996
+ cleanupExpiredCache() {
997
+ this.intermediateTokensCache.cleanup();
998
+ this.buyTokensCache.cleanup();
999
+ }
1000
+ /**
1001
+ * Get cache statistics for debugging.
1002
+ */
1003
+ getCacheStats() {
1004
+ return {
1005
+ intermediateTokens: this.intermediateTokensCache.size(),
1006
+ buyTokens: this.buyTokensCache.size()
1007
+ };
1008
+ }
1009
+ getProviderByDappId(dappId) {
1010
+ return this.config.providers.find((provider) => provider.info.dappId === dappId);
1011
+ }
581
1012
  };
582
1013
 
583
1014
  // src/providers/across/AcrossApi.ts
@@ -2924,8 +3355,8 @@ var AcrossBridgeProvider = class {
2924
3355
  status: await this.getStatus(params.bridgingId, chainId)
2925
3356
  };
2926
3357
  }
2927
- getExplorerUrl(bridgingId) {
2928
- return `https://app.across.to/transactions/${bridgingId}`;
3358
+ getExplorerUrl(_) {
3359
+ return `https://app.across.to/transactions`;
2929
3360
  }
2930
3361
  async getStatus(bridgingId, originChainId) {
2931
3362
  const depositStatus = await this.api.getDepositStatus({
@@ -3431,9 +3862,13 @@ var BUNGEE_APPROVE_AND_BRIDGE_V1_ABI = [
3431
3862
 
3432
3863
  // src/providers/bungee/BungeeApi.ts
3433
3864
  var import_sdk_common12 = require("@cowprotocol/sdk-common");
3865
+
3866
+ // src/providers/bungee/consts.ts
3867
+ var BUNGEE_API_PATH = "/api/v1/bungee";
3868
+ var BUNGEE_MANUAL_API_PATH = "/api/v1/bungee-manual";
3434
3869
  var BUNGEE_BASE_URL = "https://public-backend.bungee.exchange";
3435
- var BUNGEE_API_URL = `${BUNGEE_BASE_URL}/api/v1/bungee`;
3436
- var BUNGEE_MANUAL_API_URL = `${BUNGEE_BASE_URL}/api/v1/bungee-manual`;
3870
+ var BUNGEE_API_URL = `${BUNGEE_BASE_URL}${BUNGEE_API_PATH}`;
3871
+ var BUNGEE_MANUAL_API_URL = `${BUNGEE_BASE_URL}${BUNGEE_MANUAL_API_PATH}`;
3437
3872
  var BUNGEE_EVENTS_API_URL = "https://microservices.socket.tech/loki";
3438
3873
  var ACROSS_API_URL2 = "https://app.across.to/api";
3439
3874
  var SUPPORTED_BRIDGES = ["across", "cctp", "gnosis-native-bridge"];
@@ -3443,16 +3878,98 @@ var errorMessageMap = {
3443
3878
  across: "Across Api Error",
3444
3879
  "bungee-manual": "Bungee Manual Api Error"
3445
3880
  };
3881
+ var DEFAULT_API_OPTIONS = {
3882
+ apiBaseUrl: BUNGEE_API_URL,
3883
+ eventsApiBaseUrl: BUNGEE_EVENTS_API_URL,
3884
+ acrossApiBaseUrl: ACROSS_API_URL2,
3885
+ manualApiBaseUrl: BUNGEE_MANUAL_API_URL
3886
+ };
3887
+ var BUNGEE_API_FALLBACK_TIMEOUT = 3e5;
3888
+
3889
+ // src/providers/bungee/apiUtils.ts
3890
+ function isValidQuoteResponse(response) {
3891
+ if (typeof response !== "object" || response === null) {
3892
+ return false;
3893
+ }
3894
+ const resp = response;
3895
+ if (!("success" in resp) || !("statusCode" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || typeof resp.statusCode !== "number") {
3896
+ return false;
3897
+ }
3898
+ const result = resp.result;
3899
+ if (typeof result !== "object" || result === null) {
3900
+ return false;
3901
+ }
3902
+ const res = result;
3903
+ if (!("originChainId" in res) || !("destinationChainId" in res) || !("userAddress" in res) || !("receiverAddress" in res) || !("manualRoutes" in res) || !Array.isArray(res.manualRoutes)) {
3904
+ return false;
3905
+ }
3906
+ return res.manualRoutes.every((route) => {
3907
+ if (typeof route !== "object" || route === null) {
3908
+ return false;
3909
+ }
3910
+ const r = route;
3911
+ if (!("routeDetails" in r) || typeof r.routeDetails !== "object" || r.routeDetails === null) {
3912
+ return false;
3913
+ }
3914
+ if (!("routeFee" in r.routeDetails)) {
3915
+ return false;
3916
+ }
3917
+ const routeFee = r.routeDetails.routeFee;
3918
+ if (typeof routeFee !== "object" || routeFee === null) {
3919
+ return false;
3920
+ }
3921
+ if (!("amount" in routeFee)) {
3922
+ return false;
3923
+ }
3924
+ return "quoteId" in r && "quoteExpiry" in r && "output" in r && "gasFee" in r && "slippage" in r && "estimatedTime" in r && "routeDetails" in r;
3925
+ });
3926
+ }
3927
+ function isValidBungeeEventsResponse(response) {
3928
+ if (typeof response !== "object" || response === null) {
3929
+ return false;
3930
+ }
3931
+ const resp = response;
3932
+ if (!("success" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || !Array.isArray(resp.result)) {
3933
+ return false;
3934
+ }
3935
+ return resp.result.every((event) => {
3936
+ if (typeof event !== "object" || event === null) {
3937
+ return false;
3938
+ }
3939
+ const e = event;
3940
+ return "identifier" in e && "bridgeName" in e && "fromChainId" in e && "isCowswapTrade" in e && "orderId" in e && // 'recipient' in e &&
3941
+ "sender" in e && "srcTxStatus" in e && "destTxStatus" in e;
3942
+ });
3943
+ }
3944
+ function isValidAcrossStatusResponse(response) {
3945
+ if (typeof response !== "object" || response === null) {
3946
+ return false;
3947
+ }
3948
+ const resp = response;
3949
+ if (!("status" in resp)) {
3950
+ return false;
3951
+ }
3952
+ return true;
3953
+ }
3954
+ function isInfrastructureError(status) {
3955
+ return status >= 500 || status === 429;
3956
+ }
3957
+ function isClientFetchError(error) {
3958
+ return error instanceof TypeError || error instanceof Error && error.message?.includes("fetch");
3959
+ }
3960
+ function resolveApiEndpointFromOptions(key, options, useFallback, customUrl) {
3961
+ return useFallback ? DEFAULT_API_OPTIONS[key] : customUrl || options[key] || DEFAULT_API_OPTIONS[key];
3962
+ }
3963
+
3964
+ // src/providers/bungee/BungeeApi.ts
3446
3965
  var BungeeApi = class {
3447
- constructor(options = {
3448
- apiBaseUrl: BUNGEE_API_URL,
3449
- eventsApiBaseUrl: BUNGEE_EVENTS_API_URL,
3450
- acrossApiBaseUrl: ACROSS_API_URL2,
3451
- includeBridges: SUPPORTED_BRIDGES
3452
- }) {
3966
+ constructor(options = DEFAULT_API_OPTIONS) {
3453
3967
  this.options = options;
3454
3968
  this.validateBridges(this.getSupportedBridges());
3969
+ this.fallbackTimeoutMs = this.options.fallbackTimeoutMs ?? BUNGEE_API_FALLBACK_TIMEOUT;
3455
3970
  }
3971
+ fallbackStates = /* @__PURE__ */ new Map();
3972
+ fallbackTimeoutMs;
3456
3973
  // TODO: why do we need options.includeBridges then? Practically, you cannot add more bridges dynamically
3457
3974
  validateBridges(includeBridges) {
3458
3975
  if (includeBridges?.some((bridge) => !SUPPORTED_BRIDGES.includes(bridge))) {
@@ -3680,100 +4197,94 @@ var BungeeApi = class {
3680
4197
  getSupportedBridges(bridges) {
3681
4198
  return bridges ?? this.options.includeBridges ?? SUPPORTED_BRIDGES;
3682
4199
  }
4200
+ isBungeeApi(apiType) {
4201
+ return apiType === "bungee" || apiType === "bungee-manual";
4202
+ }
4203
+ shouldAddApiKey(apiType) {
4204
+ return this.isBungeeApi(apiType) && !!this.options.apiKey && !!this.options.customApiBaseUrl;
4205
+ }
4206
+ shouldUseFallback(apiType) {
4207
+ const fallbackState = this.fallbackStates.get(apiType);
4208
+ if (!fallbackState)
4209
+ return false;
4210
+ const now = Date.now();
4211
+ if (now > fallbackState.fallbackExpiresAt) {
4212
+ this.fallbackStates.delete(apiType);
4213
+ return false;
4214
+ }
4215
+ return fallbackState.isUsingFallback;
4216
+ }
4217
+ enableFallback(apiType) {
4218
+ const now = Date.now();
4219
+ this.fallbackStates.set(apiType, {
4220
+ isUsingFallback: true,
4221
+ fallbackExpiresAt: now + this.fallbackTimeoutMs
4222
+ });
4223
+ }
3683
4224
  shouldAddAffiliate(apiType, baseUrl) {
3684
- const isBungeeApi = apiType === "bungee" || apiType === "bungee-manual";
3685
- return !baseUrl.includes(BUNGEE_BASE_URL) && isBungeeApi;
4225
+ if (!this.isBungeeApi(apiType))
4226
+ return false;
4227
+ const defaultHost = new URL(BUNGEE_BASE_URL).host;
4228
+ const baseHost = new URL(baseUrl).host;
4229
+ return this.shouldAddApiKey(apiType) || baseHost !== defaultHost;
3686
4230
  }
3687
4231
  async makeApiCall(apiType, path, params, isValidResponse) {
4232
+ const useFallback = this.shouldUseFallback(apiType);
4233
+ const customApiBaseUrl = this.options.apiKey ? this.options.customApiBaseUrl : void 0;
3688
4234
  const baseUrlMap = {
3689
- bungee: this.options.apiBaseUrl || BUNGEE_API_URL,
3690
- events: this.options.eventsApiBaseUrl || BUNGEE_EVENTS_API_URL,
3691
- across: this.options.acrossApiBaseUrl || ACROSS_API_URL2,
3692
- "bungee-manual": this.options.manualApiBaseUrl || BUNGEE_MANUAL_API_URL
4235
+ bungee: resolveApiEndpointFromOptions(
4236
+ "apiBaseUrl",
4237
+ this.options,
4238
+ useFallback,
4239
+ customApiBaseUrl ? `${customApiBaseUrl}${BUNGEE_API_PATH}` : void 0
4240
+ ),
4241
+ "bungee-manual": resolveApiEndpointFromOptions(
4242
+ "manualApiBaseUrl",
4243
+ this.options,
4244
+ useFallback,
4245
+ customApiBaseUrl ? `${customApiBaseUrl}${BUNGEE_MANUAL_API_PATH}` : void 0
4246
+ ),
4247
+ events: resolveApiEndpointFromOptions("eventsApiBaseUrl", this.options, useFallback),
4248
+ across: resolveApiEndpointFromOptions("acrossApiBaseUrl", this.options, useFallback)
3693
4249
  };
3694
4250
  const baseUrl = baseUrlMap[apiType];
3695
4251
  const url = `${baseUrl}${path}?${new URLSearchParams(params).toString()}`;
3696
4252
  const headers = {};
4253
+ if (this.shouldAddApiKey(apiType) && this.options.apiKey) {
4254
+ headers["x-api-key"] = this.options.apiKey;
4255
+ }
3697
4256
  if (this.shouldAddAffiliate(apiType, baseUrl) && this.options.affiliate) {
3698
4257
  headers["affiliate"] = this.options.affiliate;
3699
4258
  }
3700
4259
  (0, import_sdk_common12.log)(`Fetching ${apiType} API: GET ${url}. Params: ${JSON.stringify(params)}`);
3701
- const response = await fetch(url, { method: "GET", headers });
3702
- if (!response.ok) {
3703
- const errorBody = await response.json();
3704
- throw new BridgeProviderQuoteError("API_ERROR" /* API_ERROR */, { errorBody, type: errorMessageMap[apiType] });
3705
- }
3706
- const json = await response.json();
3707
- if (isValidResponse && !isValidResponse(json)) {
3708
- throw new BridgeProviderQuoteError("INVALID_API_JSON_RESPONSE" /* INVALID_API_JSON_RESPONSE */, { json, apiType, params });
4260
+ try {
4261
+ const response = await fetch(url, { method: "GET", headers });
4262
+ if (!response.ok) {
4263
+ if (isInfrastructureError(response.status) && !useFallback) {
4264
+ this.enableFallback(apiType);
4265
+ (0, import_sdk_common12.log)(
4266
+ `Infrastructure error (${response.status}) detected for ${apiType} API. Enabling fallback for ${this.fallbackTimeoutMs}ms`
4267
+ );
4268
+ return this.makeApiCall(apiType, path, params, isValidResponse);
4269
+ }
4270
+ const errorBody = await response.json();
4271
+ throw new BridgeProviderQuoteError("API_ERROR" /* API_ERROR */, { errorBody, type: errorMessageMap[apiType] });
4272
+ }
4273
+ const json = await response.json();
4274
+ if (isValidResponse && !isValidResponse(json)) {
4275
+ throw new BridgeProviderQuoteError("INVALID_API_JSON_RESPONSE" /* INVALID_API_JSON_RESPONSE */, { json, apiType, params });
4276
+ }
4277
+ return json;
4278
+ } catch (error) {
4279
+ if (!useFallback && isClientFetchError(error)) {
4280
+ this.enableFallback(apiType);
4281
+ (0, import_sdk_common12.log)(`Network error detected for ${apiType} API. Enabling fallback for ${this.fallbackTimeoutMs}ms`);
4282
+ return this.makeApiCall(apiType, path, params, isValidResponse);
4283
+ }
4284
+ throw error;
3709
4285
  }
3710
- return json;
3711
4286
  }
3712
4287
  };
3713
- function isValidQuoteResponse(response) {
3714
- if (typeof response !== "object" || response === null) {
3715
- return false;
3716
- }
3717
- const resp = response;
3718
- if (!("success" in resp) || !("statusCode" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || typeof resp.statusCode !== "number") {
3719
- return false;
3720
- }
3721
- const result = resp.result;
3722
- if (typeof result !== "object" || result === null) {
3723
- return false;
3724
- }
3725
- const res = result;
3726
- if (!("originChainId" in res) || !("destinationChainId" in res) || !("userAddress" in res) || !("receiverAddress" in res) || !("manualRoutes" in res) || !Array.isArray(res.manualRoutes)) {
3727
- return false;
3728
- }
3729
- return res.manualRoutes.every((route) => {
3730
- if (typeof route !== "object" || route === null) {
3731
- return false;
3732
- }
3733
- const r = route;
3734
- if (!("routeDetails" in r) || typeof r.routeDetails !== "object" || r.routeDetails === null) {
3735
- return false;
3736
- }
3737
- if (!("routeFee" in r.routeDetails)) {
3738
- return false;
3739
- }
3740
- const routeFee = r.routeDetails.routeFee;
3741
- if (typeof routeFee !== "object" || routeFee === null) {
3742
- return false;
3743
- }
3744
- if (!("amount" in routeFee)) {
3745
- return false;
3746
- }
3747
- return "quoteId" in r && "quoteExpiry" in r && "output" in r && "gasFee" in r && "slippage" in r && "estimatedTime" in r && "routeDetails" in r;
3748
- });
3749
- }
3750
- function isValidBungeeEventsResponse(response) {
3751
- if (typeof response !== "object" || response === null) {
3752
- return false;
3753
- }
3754
- const resp = response;
3755
- if (!("success" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || !Array.isArray(resp.result)) {
3756
- return false;
3757
- }
3758
- return resp.result.every((event) => {
3759
- if (typeof event !== "object" || event === null) {
3760
- return false;
3761
- }
3762
- const e = event;
3763
- return "identifier" in e && "bridgeName" in e && "fromChainId" in e && "isCowswapTrade" in e && "orderId" in e && // 'recipient' in e &&
3764
- "sender" in e && "srcTxStatus" in e && "destTxStatus" in e;
3765
- });
3766
- }
3767
- function isValidAcrossStatusResponse(response) {
3768
- if (typeof response !== "object" || response === null) {
3769
- return false;
3770
- }
3771
- const resp = response;
3772
- if (!("status" in resp)) {
3773
- return false;
3774
- }
3775
- return true;
3776
- }
3777
4288
 
3778
4289
  // src/providers/bungee/createBungeeDepositCall.ts
3779
4290
  var import_sdk_config7 = require("@cowprotocol/sdk-config");