@cowprotocol/sdk-bridging 0.3.2 → 0.3.3-beta.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/README.md +0 -265
- package/dist/index.d.mts +24 -128
- package/dist/index.d.ts +24 -128
- package/dist/index.js +170 -546
- package/dist/index.mjs +170 -546
- package/package.json +13 -13
package/dist/index.mjs
CHANGED
|
@@ -76,83 +76,6 @@ function isAppDoc(appData) {
|
|
|
76
76
|
return typeof appData === "object" && appData !== null && "version" in appData && "metadata" in appData;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
// src/const.ts
|
|
80
|
-
import { RAW_FILES_PATH } from "@cowprotocol/sdk-config";
|
|
81
|
-
var RAW_PROVIDERS_FILES_PATH = `${RAW_FILES_PATH}/src/bridging/providers`;
|
|
82
|
-
var DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION = 24e4;
|
|
83
|
-
var DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION = 2e5;
|
|
84
|
-
var COW_SHED_PROXY_CREATION_GAS = 36e4;
|
|
85
|
-
var DEFAULT_EXTRA_GAS_PROXY_CREATION = 4e5;
|
|
86
|
-
var HOOK_DAPP_BRIDGE_PROVIDER_PREFIX = "cow-sdk://bridging/providers";
|
|
87
|
-
|
|
88
|
-
// src/BridgingSdk/findBridgeProviderFromHook.ts
|
|
89
|
-
function findBridgeProviderFromHook(fullAppData, providers) {
|
|
90
|
-
const postHooks = getPostHooks(fullAppData);
|
|
91
|
-
const bridgingHook = postHooks.find((hook) => {
|
|
92
|
-
return hook.dappId?.startsWith(HOOK_DAPP_BRIDGE_PROVIDER_PREFIX);
|
|
93
|
-
});
|
|
94
|
-
if (!bridgingHook) {
|
|
95
|
-
return void 0;
|
|
96
|
-
}
|
|
97
|
-
const bridgeProviderDappId = bridgingHook.dappId;
|
|
98
|
-
return providers.find((provider) => provider.info.dappId === bridgeProviderDappId);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// src/BridgingSdk/getCrossChainOrder.ts
|
|
102
|
-
async function getCrossChainOrder(params) {
|
|
103
|
-
const { chainId, orderId, orderBookApi, providers, env } = params;
|
|
104
|
-
const chainContext = { chainId, env };
|
|
105
|
-
const order = await orderBookApi.getOrder(orderId, chainContext);
|
|
106
|
-
const provider = order.fullAppData && findBridgeProviderFromHook(order.fullAppData, providers);
|
|
107
|
-
if (!provider) {
|
|
108
|
-
throw new BridgeOrderParsingError(
|
|
109
|
-
`Unknown Bridge provider in order ${order.uid}. Add provider to the SDK config to be able to decode the order`
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
const trades = await orderBookApi.getTrades({ orderUid: order.uid }, chainContext);
|
|
113
|
-
if (trades.length > 0) {
|
|
114
|
-
const firstTrade = trades[0];
|
|
115
|
-
const tradeTxHash = firstTrade?.txHash;
|
|
116
|
-
if (!tradeTxHash) {
|
|
117
|
-
throw new BridgeOrderParsingError(
|
|
118
|
-
`No tx hash found for order ${orderId} . First trade, with log index ${firstTrade?.logIndex}`
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
const { params: bridgingParams, status: statusResult } = await provider.getBridgingParams(chainId, orderId, tradeTxHash) || {};
|
|
122
|
-
if (!bridgingParams || !statusResult) {
|
|
123
|
-
throw new BridgeOrderParsingError(`Bridging params cannot be derived from transaction: ${tradeTxHash}`);
|
|
124
|
-
}
|
|
125
|
-
const state = {
|
|
126
|
-
provider,
|
|
127
|
-
chainId,
|
|
128
|
-
order,
|
|
129
|
-
statusResult: {
|
|
130
|
-
status: "unknown" /* UNKNOWN */
|
|
131
|
-
},
|
|
132
|
-
bridgingParams,
|
|
133
|
-
tradeTxHash
|
|
134
|
-
};
|
|
135
|
-
try {
|
|
136
|
-
const explorerUrl = provider.getExplorerUrl(bridgingParams.bridgingId);
|
|
137
|
-
return {
|
|
138
|
-
...state,
|
|
139
|
-
statusResult,
|
|
140
|
-
explorerUrl
|
|
141
|
-
};
|
|
142
|
-
} catch (e) {
|
|
143
|
-
console.error("Cannot get bridging status", e);
|
|
144
|
-
return state;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// src/BridgingSdk/BridgingSdk.ts
|
|
151
|
-
import { TradingSdk } from "@cowprotocol/sdk-trading";
|
|
152
|
-
import { OrderBookApi } from "@cowprotocol/sdk-order-book";
|
|
153
|
-
import { ALL_SUPPORTED_CHAINS } from "@cowprotocol/sdk-config";
|
|
154
|
-
import { enableLogging, setGlobalAdapter } from "@cowprotocol/sdk-common";
|
|
155
|
-
|
|
156
79
|
// src/BridgingSdk/getQuoteWithoutBridge.ts
|
|
157
80
|
import { jsonWithBigintReplacer, log } from "@cowprotocol/sdk-common";
|
|
158
81
|
function getQuoteWithoutBridge(params) {
|
|
@@ -203,6 +126,15 @@ async function getBridgeSignedHook(bridgeRequest, { provider, signer, hookGasLim
|
|
|
203
126
|
};
|
|
204
127
|
}
|
|
205
128
|
|
|
129
|
+
// src/const.ts
|
|
130
|
+
import { RAW_FILES_PATH } from "@cowprotocol/sdk-config";
|
|
131
|
+
var RAW_PROVIDERS_FILES_PATH = `${RAW_FILES_PATH}/src/bridging/providers`;
|
|
132
|
+
var DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION = 24e4;
|
|
133
|
+
var DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION = 2e5;
|
|
134
|
+
var COW_SHED_PROXY_CREATION_GAS = 36e4;
|
|
135
|
+
var DEFAULT_EXTRA_GAS_PROXY_CREATION = 4e5;
|
|
136
|
+
var HOOK_DAPP_BRIDGE_PROVIDER_PREFIX = "cow-sdk://bridging/providers";
|
|
137
|
+
|
|
206
138
|
// src/BridgingSdk/getQuoteWithBridge.ts
|
|
207
139
|
import { OrderKind } from "@cowprotocol/sdk-order-book";
|
|
208
140
|
import { getGlobalAdapter as getGlobalAdapter2, jsonWithBigintReplacer as jsonWithBigintReplacer2, log as log2 } from "@cowprotocol/sdk-common";
|
|
@@ -430,274 +362,73 @@ async function getBridgeResult(context) {
|
|
|
430
362
|
return { bridgeResult, bridgeHook, appDataInfo };
|
|
431
363
|
}
|
|
432
364
|
|
|
433
|
-
// src/BridgingSdk/
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
|
|
439
|
-
const { tradingSdk, providers } = config;
|
|
440
|
-
if (sellTokenChainId !== buyTokenChainId) {
|
|
441
|
-
const provider = providers[0];
|
|
442
|
-
if (!provider) {
|
|
443
|
-
throw new Error("No provider found for cross-chain swap");
|
|
444
|
-
}
|
|
445
|
-
return getQuoteWithBridge({
|
|
446
|
-
swapAndBridgeRequest: quoteBridgeRequest,
|
|
447
|
-
advancedSettings,
|
|
448
|
-
tradingSdk,
|
|
449
|
-
provider,
|
|
450
|
-
bridgeHookSigner: advancedSettings?.quoteSigner
|
|
451
|
-
});
|
|
452
|
-
} else {
|
|
453
|
-
return getQuoteWithoutBridge({
|
|
454
|
-
quoteBridgeRequest,
|
|
455
|
-
advancedSettings,
|
|
456
|
-
tradingSdk
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
// src/BridgingSdk/utils.ts
|
|
463
|
-
function validateCrossChainRequest(sellTokenChainId, buyTokenChainId) {
|
|
464
|
-
if (sellTokenChainId === buyTokenChainId) {
|
|
465
|
-
throw new BridgeProviderError(
|
|
466
|
-
"getMultiQuotes() and getBestQuote() are only for cross-chain bridging. For single-chain swaps, use getQuote() instead.",
|
|
467
|
-
{ sellTokenChainId, buyTokenChainId }
|
|
468
|
-
);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
function createBridgeQuoteTimeoutPromise(timeoutMs, prefix) {
|
|
472
|
-
return new Promise((_, reject) => {
|
|
473
|
-
setTimeout(() => {
|
|
474
|
-
reject(new BridgeProviderError(`${prefix} timeout after ${timeoutMs}ms`, {}));
|
|
475
|
-
}, timeoutMs);
|
|
365
|
+
// src/BridgingSdk/findBridgeProviderFromHook.ts
|
|
366
|
+
function findBridgeProviderFromHook(fullAppData, providers) {
|
|
367
|
+
const postHooks = getPostHooks(fullAppData);
|
|
368
|
+
const bridgingHook = postHooks.find((hook) => {
|
|
369
|
+
return hook.dappId?.startsWith(HOOK_DAPP_BRIDGE_PROVIDER_PREFIX);
|
|
476
370
|
});
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (!onQuoteResult) {
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
try {
|
|
483
|
-
onQuoteResult(result);
|
|
484
|
-
} catch (callbackError) {
|
|
485
|
-
console.warn("Error in onQuoteResult callback:", callbackError);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
function fillTimeoutResults(results, providersToQuery) {
|
|
489
|
-
for (let i = 0; i < providersToQuery.length; i++) {
|
|
490
|
-
const provider = providersToQuery[i];
|
|
491
|
-
if (!results[i] && provider) {
|
|
492
|
-
results[i] = {
|
|
493
|
-
providerDappId: provider.info.dappId,
|
|
494
|
-
quote: null,
|
|
495
|
-
error: new BridgeProviderError("Provider request timed out", {})
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
async function executeProviderQuotes(promises, timeout, config) {
|
|
501
|
-
try {
|
|
502
|
-
await Promise.race([
|
|
503
|
-
Promise.allSettled(promises),
|
|
504
|
-
createBridgeQuoteTimeoutPromise(timeout, `Multi-quote with ${config.providers.length}`)
|
|
505
|
-
]);
|
|
506
|
-
} catch {
|
|
507
|
-
console.warn("getMultiQuotes timeout occurred, returning partial results");
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
function isBetterQuote(quote1, quote2) {
|
|
511
|
-
if (!quote2 || !quote2.quote) {
|
|
512
|
-
return !!quote1.quote;
|
|
513
|
-
}
|
|
514
|
-
if (!quote1.quote) {
|
|
515
|
-
return false;
|
|
516
|
-
}
|
|
517
|
-
const quote1BuyAmount = quote1.quote.bridge.amountsAndCosts.afterSlippage.buyAmount;
|
|
518
|
-
const quote2BuyAmount = quote2.quote.bridge.amountsAndCosts.afterSlippage.buyAmount;
|
|
519
|
-
return quote1BuyAmount > quote2BuyAmount;
|
|
520
|
-
}
|
|
521
|
-
function safeCallBestQuoteCallback(onQuoteResult, result) {
|
|
522
|
-
if (!onQuoteResult) {
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
try {
|
|
526
|
-
onQuoteResult(result);
|
|
527
|
-
} catch (callbackError) {
|
|
528
|
-
console.warn("Error in onQuoteResult callback:", callbackError);
|
|
371
|
+
if (!bridgingHook) {
|
|
372
|
+
return void 0;
|
|
529
373
|
}
|
|
374
|
+
const bridgeProviderDappId = bridgingHook.dappId;
|
|
375
|
+
return providers.find((provider) => provider.info.dappId === bridgeProviderDappId);
|
|
530
376
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
377
|
+
|
|
378
|
+
// src/BridgingSdk/getCrossChainOrder.ts
|
|
379
|
+
async function getCrossChainOrder(params) {
|
|
380
|
+
const { chainId, orderId, orderBookApi, providers, env } = params;
|
|
381
|
+
const chainContext = { chainId, env };
|
|
382
|
+
const order = await orderBookApi.getOrder(orderId, chainContext);
|
|
383
|
+
const provider = order.fullAppData && findBridgeProviderFromHook(order.fullAppData, providers);
|
|
384
|
+
if (!provider) {
|
|
385
|
+
throw new BridgeOrderParsingError(
|
|
386
|
+
`Unknown Bridge provider in order ${order.uid}. Add provider to the SDK config to be able to decode the order`
|
|
387
|
+
);
|
|
534
388
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
389
|
+
const trades = await orderBookApi.getTrades({ orderUid: order.uid }, chainContext);
|
|
390
|
+
if (trades.length > 0) {
|
|
391
|
+
const firstTrade = trades[0];
|
|
392
|
+
const tradeTxHash = firstTrade?.txHash;
|
|
393
|
+
if (!tradeTxHash) {
|
|
394
|
+
throw new BridgeOrderParsingError(
|
|
395
|
+
`No tx hash found for order ${orderId} . First trade, with log index ${firstTrade?.logIndex}`
|
|
541
396
|
);
|
|
542
397
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// src/BridgingSdk/strategies/MultiQuoteStrategy.ts
|
|
548
|
-
var DEFAULT_TOTAL_TIMEOUT_MS = 4e4;
|
|
549
|
-
var DEFAULT_PROVIDER_TIMEOUT_MS = 2e4;
|
|
550
|
-
var MultiQuoteStrategyImpl = class {
|
|
551
|
-
strategyName = "MultiQuoteStrategy";
|
|
552
|
-
async execute(request, config) {
|
|
553
|
-
const { quoteBridgeRequest, providerDappIds, advancedSettings, options } = request;
|
|
554
|
-
const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
|
|
555
|
-
validateCrossChainRequest(sellTokenChainId, buyTokenChainId);
|
|
556
|
-
const providersToQuery = resolveProvidersToQuery(providerDappIds, config.providers);
|
|
557
|
-
const {
|
|
558
|
-
onQuoteResult,
|
|
559
|
-
totalTimeout = DEFAULT_TOTAL_TIMEOUT_MS,
|
|
560
|
-
providerTimeout = DEFAULT_PROVIDER_TIMEOUT_MS
|
|
561
|
-
} = options || {};
|
|
562
|
-
const results = [];
|
|
563
|
-
const promises = [];
|
|
564
|
-
for (let i = 0; i < providersToQuery.length; i++) {
|
|
565
|
-
const provider = providersToQuery[i];
|
|
566
|
-
if (!provider) {
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
const context = {
|
|
570
|
-
provider,
|
|
571
|
-
quoteBridgeRequest,
|
|
572
|
-
advancedSettings,
|
|
573
|
-
providerTimeout,
|
|
574
|
-
onQuoteResult,
|
|
575
|
-
results,
|
|
576
|
-
index: i
|
|
577
|
-
};
|
|
578
|
-
const promise = this.createProviderQuotePromise(context, config);
|
|
579
|
-
promises.push(promise);
|
|
398
|
+
const { params: bridgingParams, status: statusResult } = await provider.getBridgingParams(chainId, orderId, tradeTxHash) || {};
|
|
399
|
+
if (!bridgingParams || !statusResult) {
|
|
400
|
+
throw new BridgeOrderParsingError(`Bridging params cannot be derived from transaction: ${tradeTxHash}`);
|
|
580
401
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
getQuoteWithBridge({
|
|
598
|
-
swapAndBridgeRequest: quoteBridgeRequest,
|
|
599
|
-
advancedSettings,
|
|
600
|
-
tradingSdk: config.tradingSdk,
|
|
601
|
-
provider,
|
|
602
|
-
bridgeHookSigner: advancedSettings?.quoteSigner
|
|
603
|
-
}),
|
|
604
|
-
createBridgeQuoteTimeoutPromise(providerTimeout, `Provider ${provider.info.dappId}`)
|
|
605
|
-
]);
|
|
606
|
-
const result = {
|
|
607
|
-
providerDappId: provider.info.dappId,
|
|
608
|
-
quote,
|
|
609
|
-
error: void 0
|
|
610
|
-
};
|
|
611
|
-
results[index] = result;
|
|
612
|
-
safeCallProgressiveCallback(onQuoteResult, result);
|
|
613
|
-
} catch (error) {
|
|
614
|
-
const result = {
|
|
615
|
-
providerDappId: provider.info.dappId,
|
|
616
|
-
quote: null,
|
|
617
|
-
error: error instanceof Error ? error : new BridgeProviderError(String(error), {})
|
|
618
|
-
};
|
|
619
|
-
results[index] = result;
|
|
620
|
-
safeCallProgressiveCallback(onQuoteResult, result);
|
|
621
|
-
}
|
|
622
|
-
})();
|
|
623
|
-
}
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
// src/BridgingSdk/strategies/BestQuoteStrategy.ts
|
|
627
|
-
var DEFAULT_TOTAL_TIMEOUT_MS2 = 4e4;
|
|
628
|
-
var DEFAULT_PROVIDER_TIMEOUT_MS2 = 2e4;
|
|
629
|
-
var BestQuoteStrategyImpl = class {
|
|
630
|
-
strategyName = "BestQuoteStrategy";
|
|
631
|
-
async execute(request, config) {
|
|
632
|
-
const { quoteBridgeRequest, providerDappIds, advancedSettings, options } = request;
|
|
633
|
-
const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
|
|
634
|
-
validateCrossChainRequest(sellTokenChainId, buyTokenChainId);
|
|
635
|
-
const providersToQuery = resolveProvidersToQuery(providerDappIds, config.providers);
|
|
636
|
-
const {
|
|
637
|
-
onQuoteResult,
|
|
638
|
-
totalTimeout = DEFAULT_TOTAL_TIMEOUT_MS2,
|
|
639
|
-
providerTimeout = DEFAULT_PROVIDER_TIMEOUT_MS2
|
|
640
|
-
} = options || {};
|
|
641
|
-
const bestResult = { current: null };
|
|
642
|
-
const firstError = { current: null };
|
|
643
|
-
const promises = [];
|
|
644
|
-
for (const provider of providersToQuery) {
|
|
645
|
-
const context = {
|
|
646
|
-
provider,
|
|
647
|
-
quoteBridgeRequest,
|
|
648
|
-
advancedSettings,
|
|
649
|
-
providerTimeout,
|
|
650
|
-
onQuoteResult,
|
|
651
|
-
bestResult,
|
|
652
|
-
firstError
|
|
402
|
+
const state = {
|
|
403
|
+
provider,
|
|
404
|
+
chainId,
|
|
405
|
+
order,
|
|
406
|
+
statusResult: {
|
|
407
|
+
status: "unknown" /* UNKNOWN */
|
|
408
|
+
},
|
|
409
|
+
bridgingParams,
|
|
410
|
+
tradeTxHash
|
|
411
|
+
};
|
|
412
|
+
try {
|
|
413
|
+
const explorerUrl = provider.getExplorerUrl(bridgingParams.bridgingId);
|
|
414
|
+
return {
|
|
415
|
+
...state,
|
|
416
|
+
statusResult,
|
|
417
|
+
explorerUrl
|
|
653
418
|
};
|
|
654
|
-
|
|
655
|
-
|
|
419
|
+
} catch (e) {
|
|
420
|
+
console.error("Cannot get bridging status", e);
|
|
421
|
+
return state;
|
|
656
422
|
}
|
|
657
|
-
await executeProviderQuotes(promises, totalTimeout, config);
|
|
658
|
-
return bestResult.current || firstError.current;
|
|
659
|
-
}
|
|
660
|
-
createBestQuoteProviderPromise(context, config) {
|
|
661
|
-
const { provider, quoteBridgeRequest, advancedSettings, providerTimeout, onQuoteResult, bestResult, firstError } = context;
|
|
662
|
-
return (async () => {
|
|
663
|
-
try {
|
|
664
|
-
const quote = await Promise.race([
|
|
665
|
-
getQuoteWithBridge({
|
|
666
|
-
swapAndBridgeRequest: quoteBridgeRequest,
|
|
667
|
-
advancedSettings,
|
|
668
|
-
tradingSdk: config.tradingSdk,
|
|
669
|
-
provider,
|
|
670
|
-
bridgeHookSigner: advancedSettings?.quoteSigner
|
|
671
|
-
}),
|
|
672
|
-
createBridgeQuoteTimeoutPromise(providerTimeout, `Provider ${provider.info.dappId}`)
|
|
673
|
-
]);
|
|
674
|
-
const result = {
|
|
675
|
-
providerDappId: provider.info.dappId,
|
|
676
|
-
quote,
|
|
677
|
-
error: void 0
|
|
678
|
-
};
|
|
679
|
-
if (isBetterQuote(result, bestResult.current)) {
|
|
680
|
-
bestResult.current = result;
|
|
681
|
-
safeCallBestQuoteCallback(onQuoteResult, result);
|
|
682
|
-
}
|
|
683
|
-
} catch (error) {
|
|
684
|
-
const errorResult = {
|
|
685
|
-
providerDappId: provider.info.dappId,
|
|
686
|
-
quote: null,
|
|
687
|
-
error: error instanceof Error ? error : new BridgeProviderError(String(error), {})
|
|
688
|
-
};
|
|
689
|
-
if (!firstError.current) {
|
|
690
|
-
firstError.current = errorResult;
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
})();
|
|
694
423
|
}
|
|
695
|
-
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
696
426
|
|
|
697
427
|
// src/BridgingSdk/BridgingSdk.ts
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
428
|
+
import { TradingSdk } from "@cowprotocol/sdk-trading";
|
|
429
|
+
import { OrderBookApi } from "@cowprotocol/sdk-order-book";
|
|
430
|
+
import { ALL_SUPPORTED_CHAINS } from "@cowprotocol/sdk-config";
|
|
431
|
+
import { enableLogging, setGlobalAdapter } from "@cowprotocol/sdk-common";
|
|
701
432
|
var BridgingSdk = class {
|
|
702
433
|
constructor(options, adapter) {
|
|
703
434
|
this.options = options;
|
|
@@ -705,8 +436,8 @@ var BridgingSdk = class {
|
|
|
705
436
|
setGlobalAdapter(adapter);
|
|
706
437
|
}
|
|
707
438
|
const { providers, ...restOptions } = options;
|
|
708
|
-
if (!providers || providers.length
|
|
709
|
-
throw new Error("
|
|
439
|
+
if (!providers || providers.length !== 1) {
|
|
440
|
+
throw new Error("Current implementation only supports a single bridge provider");
|
|
710
441
|
}
|
|
711
442
|
if (options.enableLogging !== void 0) {
|
|
712
443
|
enableLogging(options.enableLogging);
|
|
@@ -770,47 +501,23 @@ var BridgingSdk = class {
|
|
|
770
501
|
* @throws Error if no path is found
|
|
771
502
|
*/
|
|
772
503
|
async getQuote(quoteBridgeRequest, advancedSettings) {
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
* @returns Array of results, one for each provider (successful quotes or errors)
|
|
791
|
-
* @throws Error if the request is for a single-chain swap (sellTokenChainId === buyTokenChainId)
|
|
792
|
-
* ```
|
|
793
|
-
*/
|
|
794
|
-
async getMultiQuotes(request) {
|
|
795
|
-
return multiQuoteStrategy.execute(request, this.config);
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Get the best quote from multiple bridge providers with progressive updates.
|
|
799
|
-
*
|
|
800
|
-
* This method is specifically for cross-chain bridging quotes. For single-chain swaps, use getQuote() instead.
|
|
801
|
-
*
|
|
802
|
-
* Features:
|
|
803
|
-
* - Returns only the best quote based on buyAmount after slippage
|
|
804
|
-
* - Progressive updates: Use the `onQuoteResult` callback to receive updates whenever a better quote is found
|
|
805
|
-
* - Timeout support: Configure maximum wait time for all providers and individual provider timeouts
|
|
806
|
-
* - Parallel execution: All providers are queried simultaneously for best performance
|
|
807
|
-
*
|
|
808
|
-
* @param request - The best quote request containing quote parameters, provider dappIds, and options
|
|
809
|
-
* @returns The best quote result found, or null if no successful quotes were obtained
|
|
810
|
-
* @throws Error if the request is for a single-chain swap (sellTokenChainId === buyTokenChainId)
|
|
811
|
-
*/
|
|
812
|
-
async getBestQuote(request) {
|
|
813
|
-
return bestQuoteStrategy.execute(request, this.config);
|
|
504
|
+
const { sellTokenChainId, buyTokenChainId } = quoteBridgeRequest;
|
|
505
|
+
const tradingSdk = this.config.tradingSdk;
|
|
506
|
+
if (sellTokenChainId !== buyTokenChainId) {
|
|
507
|
+
return getQuoteWithBridge({
|
|
508
|
+
swapAndBridgeRequest: quoteBridgeRequest,
|
|
509
|
+
advancedSettings,
|
|
510
|
+
tradingSdk,
|
|
511
|
+
provider: this.provider,
|
|
512
|
+
bridgeHookSigner: advancedSettings?.quoteSigner
|
|
513
|
+
});
|
|
514
|
+
} else {
|
|
515
|
+
return getQuoteWithoutBridge({
|
|
516
|
+
quoteBridgeRequest,
|
|
517
|
+
advancedSettings,
|
|
518
|
+
tradingSdk
|
|
519
|
+
});
|
|
520
|
+
}
|
|
814
521
|
}
|
|
815
522
|
async getOrder(params) {
|
|
816
523
|
const { orderBookApi } = this.config;
|
|
@@ -829,9 +536,6 @@ var BridgingSdk = class {
|
|
|
829
536
|
getProviderFromAppData(fullAppData) {
|
|
830
537
|
return findBridgeProviderFromHook(fullAppData, this.getProviders());
|
|
831
538
|
}
|
|
832
|
-
getProviderByDappId(dappId) {
|
|
833
|
-
return this.config.providers.find((provider) => provider.info.dappId === dappId);
|
|
834
|
-
}
|
|
835
539
|
};
|
|
836
540
|
|
|
837
541
|
// src/providers/across/AcrossApi.ts
|
|
@@ -3691,13 +3395,9 @@ var BUNGEE_APPROVE_AND_BRIDGE_V1_ABI = [
|
|
|
3691
3395
|
|
|
3692
3396
|
// src/providers/bungee/BungeeApi.ts
|
|
3693
3397
|
import { getGlobalAdapter as getGlobalAdapter8, log as log5 } from "@cowprotocol/sdk-common";
|
|
3694
|
-
|
|
3695
|
-
// src/providers/bungee/consts.ts
|
|
3696
|
-
var BUNGEE_API_PATH = "/api/v1/bungee";
|
|
3697
|
-
var BUNGEE_MANUAL_API_PATH = "/api/v1/bungee-manual";
|
|
3698
3398
|
var BUNGEE_BASE_URL = "https://public-backend.bungee.exchange";
|
|
3699
|
-
var BUNGEE_API_URL = `${BUNGEE_BASE_URL}
|
|
3700
|
-
var BUNGEE_MANUAL_API_URL = `${BUNGEE_BASE_URL}
|
|
3399
|
+
var BUNGEE_API_URL = `${BUNGEE_BASE_URL}/api/v1/bungee`;
|
|
3400
|
+
var BUNGEE_MANUAL_API_URL = `${BUNGEE_BASE_URL}/api/v1/bungee-manual`;
|
|
3701
3401
|
var BUNGEE_EVENTS_API_URL = "https://microservices.socket.tech/loki";
|
|
3702
3402
|
var ACROSS_API_URL2 = "https://app.across.to/api";
|
|
3703
3403
|
var SUPPORTED_BRIDGES = ["across", "cctp", "gnosis-native-bridge"];
|
|
@@ -3707,98 +3407,16 @@ var errorMessageMap = {
|
|
|
3707
3407
|
across: "Across Api Error",
|
|
3708
3408
|
"bungee-manual": "Bungee Manual Api Error"
|
|
3709
3409
|
};
|
|
3710
|
-
var DEFAULT_API_OPTIONS = {
|
|
3711
|
-
apiBaseUrl: BUNGEE_API_URL,
|
|
3712
|
-
eventsApiBaseUrl: BUNGEE_EVENTS_API_URL,
|
|
3713
|
-
acrossApiBaseUrl: ACROSS_API_URL2,
|
|
3714
|
-
manualApiBaseUrl: BUNGEE_MANUAL_API_URL
|
|
3715
|
-
};
|
|
3716
|
-
var BUNGEE_API_FALLBACK_TIMEOUT = 3e5;
|
|
3717
|
-
|
|
3718
|
-
// src/providers/bungee/apiUtils.ts
|
|
3719
|
-
function isValidQuoteResponse(response) {
|
|
3720
|
-
if (typeof response !== "object" || response === null) {
|
|
3721
|
-
return false;
|
|
3722
|
-
}
|
|
3723
|
-
const resp = response;
|
|
3724
|
-
if (!("success" in resp) || !("statusCode" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || typeof resp.statusCode !== "number") {
|
|
3725
|
-
return false;
|
|
3726
|
-
}
|
|
3727
|
-
const result = resp.result;
|
|
3728
|
-
if (typeof result !== "object" || result === null) {
|
|
3729
|
-
return false;
|
|
3730
|
-
}
|
|
3731
|
-
const res = result;
|
|
3732
|
-
if (!("originChainId" in res) || !("destinationChainId" in res) || !("userAddress" in res) || !("receiverAddress" in res) || !("manualRoutes" in res) || !Array.isArray(res.manualRoutes)) {
|
|
3733
|
-
return false;
|
|
3734
|
-
}
|
|
3735
|
-
return res.manualRoutes.every((route) => {
|
|
3736
|
-
if (typeof route !== "object" || route === null) {
|
|
3737
|
-
return false;
|
|
3738
|
-
}
|
|
3739
|
-
const r = route;
|
|
3740
|
-
if (!("routeDetails" in r) || typeof r.routeDetails !== "object" || r.routeDetails === null) {
|
|
3741
|
-
return false;
|
|
3742
|
-
}
|
|
3743
|
-
if (!("routeFee" in r.routeDetails)) {
|
|
3744
|
-
return false;
|
|
3745
|
-
}
|
|
3746
|
-
const routeFee = r.routeDetails.routeFee;
|
|
3747
|
-
if (typeof routeFee !== "object" || routeFee === null) {
|
|
3748
|
-
return false;
|
|
3749
|
-
}
|
|
3750
|
-
if (!("amount" in routeFee)) {
|
|
3751
|
-
return false;
|
|
3752
|
-
}
|
|
3753
|
-
return "quoteId" in r && "quoteExpiry" in r && "output" in r && "gasFee" in r && "slippage" in r && "estimatedTime" in r && "routeDetails" in r;
|
|
3754
|
-
});
|
|
3755
|
-
}
|
|
3756
|
-
function isValidBungeeEventsResponse(response) {
|
|
3757
|
-
if (typeof response !== "object" || response === null) {
|
|
3758
|
-
return false;
|
|
3759
|
-
}
|
|
3760
|
-
const resp = response;
|
|
3761
|
-
if (!("success" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || !Array.isArray(resp.result)) {
|
|
3762
|
-
return false;
|
|
3763
|
-
}
|
|
3764
|
-
return resp.result.every((event) => {
|
|
3765
|
-
if (typeof event !== "object" || event === null) {
|
|
3766
|
-
return false;
|
|
3767
|
-
}
|
|
3768
|
-
const e = event;
|
|
3769
|
-
return "identifier" in e && "bridgeName" in e && "fromChainId" in e && "isCowswapTrade" in e && "orderId" in e && // 'recipient' in e &&
|
|
3770
|
-
"sender" in e && "srcTxStatus" in e && "destTxStatus" in e;
|
|
3771
|
-
});
|
|
3772
|
-
}
|
|
3773
|
-
function isValidAcrossStatusResponse(response) {
|
|
3774
|
-
if (typeof response !== "object" || response === null) {
|
|
3775
|
-
return false;
|
|
3776
|
-
}
|
|
3777
|
-
const resp = response;
|
|
3778
|
-
if (!("status" in resp)) {
|
|
3779
|
-
return false;
|
|
3780
|
-
}
|
|
3781
|
-
return true;
|
|
3782
|
-
}
|
|
3783
|
-
function isInfrastructureError(status) {
|
|
3784
|
-
return status >= 500 || status === 429;
|
|
3785
|
-
}
|
|
3786
|
-
function isClientFetchError(error) {
|
|
3787
|
-
return error instanceof TypeError || error instanceof Error && error.message?.includes("fetch");
|
|
3788
|
-
}
|
|
3789
|
-
function resolveApiEndpointFromOptions(key, options, useFallback, customUrl) {
|
|
3790
|
-
return useFallback ? DEFAULT_API_OPTIONS[key] : customUrl || options[key] || DEFAULT_API_OPTIONS[key];
|
|
3791
|
-
}
|
|
3792
|
-
|
|
3793
|
-
// src/providers/bungee/BungeeApi.ts
|
|
3794
3410
|
var BungeeApi = class {
|
|
3795
|
-
constructor(options =
|
|
3411
|
+
constructor(options = {
|
|
3412
|
+
apiBaseUrl: BUNGEE_API_URL,
|
|
3413
|
+
eventsApiBaseUrl: BUNGEE_EVENTS_API_URL,
|
|
3414
|
+
acrossApiBaseUrl: ACROSS_API_URL2,
|
|
3415
|
+
includeBridges: SUPPORTED_BRIDGES
|
|
3416
|
+
}) {
|
|
3796
3417
|
this.options = options;
|
|
3797
3418
|
this.validateBridges(this.getSupportedBridges());
|
|
3798
|
-
this.fallbackTimeoutMs = this.options.fallbackTimeoutMs ?? BUNGEE_API_FALLBACK_TIMEOUT;
|
|
3799
3419
|
}
|
|
3800
|
-
fallbackStates = /* @__PURE__ */ new Map();
|
|
3801
|
-
fallbackTimeoutMs;
|
|
3802
3420
|
// TODO: why do we need options.includeBridges then? Practically, you cannot add more bridges dynamically
|
|
3803
3421
|
validateBridges(includeBridges) {
|
|
3804
3422
|
if (includeBridges?.some((bridge) => !SUPPORTED_BRIDGES.includes(bridge))) {
|
|
@@ -4026,94 +3644,100 @@ var BungeeApi = class {
|
|
|
4026
3644
|
getSupportedBridges(bridges) {
|
|
4027
3645
|
return bridges ?? this.options.includeBridges ?? SUPPORTED_BRIDGES;
|
|
4028
3646
|
}
|
|
4029
|
-
isBungeeApi(apiType) {
|
|
4030
|
-
return apiType === "bungee" || apiType === "bungee-manual";
|
|
4031
|
-
}
|
|
4032
|
-
shouldAddApiKey(apiType) {
|
|
4033
|
-
return this.isBungeeApi(apiType) && !!this.options.apiKey && !!this.options.customApiBaseUrl;
|
|
4034
|
-
}
|
|
4035
|
-
shouldUseFallback(apiType) {
|
|
4036
|
-
const fallbackState = this.fallbackStates.get(apiType);
|
|
4037
|
-
if (!fallbackState)
|
|
4038
|
-
return false;
|
|
4039
|
-
const now = Date.now();
|
|
4040
|
-
if (now > fallbackState.fallbackExpiresAt) {
|
|
4041
|
-
this.fallbackStates.delete(apiType);
|
|
4042
|
-
return false;
|
|
4043
|
-
}
|
|
4044
|
-
return fallbackState.isUsingFallback;
|
|
4045
|
-
}
|
|
4046
|
-
enableFallback(apiType) {
|
|
4047
|
-
const now = Date.now();
|
|
4048
|
-
this.fallbackStates.set(apiType, {
|
|
4049
|
-
isUsingFallback: true,
|
|
4050
|
-
fallbackExpiresAt: now + this.fallbackTimeoutMs
|
|
4051
|
-
});
|
|
4052
|
-
}
|
|
4053
3647
|
shouldAddAffiliate(apiType, baseUrl) {
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
const defaultHost = new URL(BUNGEE_BASE_URL).host;
|
|
4057
|
-
const baseHost = new URL(baseUrl).host;
|
|
4058
|
-
return this.shouldAddApiKey(apiType) || baseHost !== defaultHost;
|
|
3648
|
+
const isBungeeApi = apiType === "bungee" || apiType === "bungee-manual";
|
|
3649
|
+
return !baseUrl.includes(BUNGEE_BASE_URL) && isBungeeApi;
|
|
4059
3650
|
}
|
|
4060
3651
|
async makeApiCall(apiType, path, params, isValidResponse) {
|
|
4061
|
-
const useFallback = this.shouldUseFallback(apiType);
|
|
4062
|
-
const customApiBaseUrl = this.options.apiKey ? this.options.customApiBaseUrl : void 0;
|
|
4063
3652
|
const baseUrlMap = {
|
|
4064
|
-
bungee:
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
customApiBaseUrl ? `${customApiBaseUrl}${BUNGEE_API_PATH}` : void 0
|
|
4069
|
-
),
|
|
4070
|
-
"bungee-manual": resolveApiEndpointFromOptions(
|
|
4071
|
-
"manualApiBaseUrl",
|
|
4072
|
-
this.options,
|
|
4073
|
-
useFallback,
|
|
4074
|
-
customApiBaseUrl ? `${customApiBaseUrl}${BUNGEE_MANUAL_API_PATH}` : void 0
|
|
4075
|
-
),
|
|
4076
|
-
events: resolveApiEndpointFromOptions("eventsApiBaseUrl", this.options, useFallback),
|
|
4077
|
-
across: resolveApiEndpointFromOptions("acrossApiBaseUrl", this.options, useFallback)
|
|
3653
|
+
bungee: this.options.apiBaseUrl || BUNGEE_API_URL,
|
|
3654
|
+
events: this.options.eventsApiBaseUrl || BUNGEE_EVENTS_API_URL,
|
|
3655
|
+
across: this.options.acrossApiBaseUrl || ACROSS_API_URL2,
|
|
3656
|
+
"bungee-manual": this.options.manualApiBaseUrl || BUNGEE_MANUAL_API_URL
|
|
4078
3657
|
};
|
|
4079
3658
|
const baseUrl = baseUrlMap[apiType];
|
|
4080
3659
|
const url = `${baseUrl}${path}?${new URLSearchParams(params).toString()}`;
|
|
4081
3660
|
const headers = {};
|
|
4082
|
-
if (this.shouldAddApiKey(apiType) && this.options.apiKey) {
|
|
4083
|
-
headers["x-api-key"] = this.options.apiKey;
|
|
4084
|
-
}
|
|
4085
3661
|
if (this.shouldAddAffiliate(apiType, baseUrl) && this.options.affiliate) {
|
|
4086
3662
|
headers["affiliate"] = this.options.affiliate;
|
|
4087
3663
|
}
|
|
4088
3664
|
log5(`Fetching ${apiType} API: GET ${url}. Params: ${JSON.stringify(params)}`);
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
this.enableFallback(apiType);
|
|
4094
|
-
log5(
|
|
4095
|
-
`Infrastructure error (${response.status}) detected for ${apiType} API. Enabling fallback for ${this.fallbackTimeoutMs}ms`
|
|
4096
|
-
);
|
|
4097
|
-
return this.makeApiCall(apiType, path, params, isValidResponse);
|
|
4098
|
-
}
|
|
4099
|
-
const errorBody = await response.json();
|
|
4100
|
-
throw new BridgeProviderQuoteError("API_ERROR" /* API_ERROR */, { errorBody, type: errorMessageMap[apiType] });
|
|
4101
|
-
}
|
|
4102
|
-
const json = await response.json();
|
|
4103
|
-
if (isValidResponse && !isValidResponse(json)) {
|
|
4104
|
-
throw new BridgeProviderQuoteError("INVALID_API_JSON_RESPONSE" /* INVALID_API_JSON_RESPONSE */, { json, apiType, params });
|
|
4105
|
-
}
|
|
4106
|
-
return json;
|
|
4107
|
-
} catch (error) {
|
|
4108
|
-
if (!useFallback && isClientFetchError(error)) {
|
|
4109
|
-
this.enableFallback(apiType);
|
|
4110
|
-
log5(`Network error detected for ${apiType} API. Enabling fallback for ${this.fallbackTimeoutMs}ms`);
|
|
4111
|
-
return this.makeApiCall(apiType, path, params, isValidResponse);
|
|
4112
|
-
}
|
|
4113
|
-
throw error;
|
|
3665
|
+
const response = await fetch(url, { method: "GET", headers });
|
|
3666
|
+
if (!response.ok) {
|
|
3667
|
+
const errorBody = await response.json();
|
|
3668
|
+
throw new BridgeProviderQuoteError("API_ERROR" /* API_ERROR */, { errorBody, type: errorMessageMap[apiType] });
|
|
4114
3669
|
}
|
|
3670
|
+
const json = await response.json();
|
|
3671
|
+
if (isValidResponse && !isValidResponse(json)) {
|
|
3672
|
+
throw new BridgeProviderQuoteError("INVALID_API_JSON_RESPONSE" /* INVALID_API_JSON_RESPONSE */, { json, apiType, params });
|
|
3673
|
+
}
|
|
3674
|
+
return json;
|
|
4115
3675
|
}
|
|
4116
3676
|
};
|
|
3677
|
+
function isValidQuoteResponse(response) {
|
|
3678
|
+
if (typeof response !== "object" || response === null) {
|
|
3679
|
+
return false;
|
|
3680
|
+
}
|
|
3681
|
+
const resp = response;
|
|
3682
|
+
if (!("success" in resp) || !("statusCode" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || typeof resp.statusCode !== "number") {
|
|
3683
|
+
return false;
|
|
3684
|
+
}
|
|
3685
|
+
const result = resp.result;
|
|
3686
|
+
if (typeof result !== "object" || result === null) {
|
|
3687
|
+
return false;
|
|
3688
|
+
}
|
|
3689
|
+
const res = result;
|
|
3690
|
+
if (!("originChainId" in res) || !("destinationChainId" in res) || !("userAddress" in res) || !("receiverAddress" in res) || !("manualRoutes" in res) || !Array.isArray(res.manualRoutes)) {
|
|
3691
|
+
return false;
|
|
3692
|
+
}
|
|
3693
|
+
return res.manualRoutes.every((route) => {
|
|
3694
|
+
if (typeof route !== "object" || route === null) {
|
|
3695
|
+
return false;
|
|
3696
|
+
}
|
|
3697
|
+
const r = route;
|
|
3698
|
+
if (!("routeDetails" in r) || typeof r.routeDetails !== "object" || r.routeDetails === null) {
|
|
3699
|
+
return false;
|
|
3700
|
+
}
|
|
3701
|
+
if (!("routeFee" in r.routeDetails)) {
|
|
3702
|
+
return false;
|
|
3703
|
+
}
|
|
3704
|
+
const routeFee = r.routeDetails.routeFee;
|
|
3705
|
+
if (typeof routeFee !== "object" || routeFee === null) {
|
|
3706
|
+
return false;
|
|
3707
|
+
}
|
|
3708
|
+
if (!("amount" in routeFee)) {
|
|
3709
|
+
return false;
|
|
3710
|
+
}
|
|
3711
|
+
return "quoteId" in r && "quoteExpiry" in r && "output" in r && "gasFee" in r && "slippage" in r && "estimatedTime" in r && "routeDetails" in r;
|
|
3712
|
+
});
|
|
3713
|
+
}
|
|
3714
|
+
function isValidBungeeEventsResponse(response) {
|
|
3715
|
+
if (typeof response !== "object" || response === null) {
|
|
3716
|
+
return false;
|
|
3717
|
+
}
|
|
3718
|
+
const resp = response;
|
|
3719
|
+
if (!("success" in resp) || !("result" in resp) || typeof resp.success !== "boolean" || !Array.isArray(resp.result)) {
|
|
3720
|
+
return false;
|
|
3721
|
+
}
|
|
3722
|
+
return resp.result.every((event) => {
|
|
3723
|
+
if (typeof event !== "object" || event === null) {
|
|
3724
|
+
return false;
|
|
3725
|
+
}
|
|
3726
|
+
const e = event;
|
|
3727
|
+
return "identifier" in e && "bridgeName" in e && "fromChainId" in e && "isCowswapTrade" in e && "orderId" in e && // 'recipient' in e &&
|
|
3728
|
+
"sender" in e && "srcTxStatus" in e && "destTxStatus" in e;
|
|
3729
|
+
});
|
|
3730
|
+
}
|
|
3731
|
+
function isValidAcrossStatusResponse(response) {
|
|
3732
|
+
if (typeof response !== "object" || response === null) {
|
|
3733
|
+
return false;
|
|
3734
|
+
}
|
|
3735
|
+
const resp = response;
|
|
3736
|
+
if (!("status" in resp)) {
|
|
3737
|
+
return false;
|
|
3738
|
+
}
|
|
3739
|
+
return true;
|
|
3740
|
+
}
|
|
4117
3741
|
|
|
4118
3742
|
// src/providers/bungee/createBungeeDepositCall.ts
|
|
4119
3743
|
import { ETH_ADDRESS } from "@cowprotocol/sdk-config";
|