@hyperlane-xyz/rebalancer 2.0.0 → 3.0.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/bridges/LiFiBridge.d.ts +67 -0
- package/dist/bridges/LiFiBridge.d.ts.map +1 -0
- package/dist/bridges/LiFiBridge.js +386 -0
- package/dist/bridges/LiFiBridge.js.map +1 -0
- package/dist/config/RebalancerConfig.d.ts +7 -2
- package/dist/config/RebalancerConfig.d.ts.map +1 -1
- package/dist/config/RebalancerConfig.js +7 -4
- package/dist/config/RebalancerConfig.js.map +1 -1
- package/dist/config/RebalancerConfig.test.js +134 -1
- package/dist/config/RebalancerConfig.test.js.map +1 -1
- package/dist/config/types.d.ts +1016 -304
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +105 -10
- package/dist/config/types.js.map +1 -1
- package/dist/core/InventoryRebalancer.d.ts +190 -0
- package/dist/core/InventoryRebalancer.d.ts.map +1 -0
- package/dist/core/InventoryRebalancer.js +885 -0
- package/dist/core/InventoryRebalancer.js.map +1 -0
- package/dist/core/InventoryRebalancer.test.d.ts +2 -0
- package/dist/core/InventoryRebalancer.test.d.ts.map +1 -0
- package/dist/core/InventoryRebalancer.test.js +1351 -0
- package/dist/core/InventoryRebalancer.test.js.map +1 -0
- package/dist/core/Rebalancer.d.ts +11 -4
- package/dist/core/Rebalancer.d.ts.map +1 -1
- package/dist/core/Rebalancer.js +92 -9
- package/dist/core/Rebalancer.js.map +1 -1
- package/dist/core/Rebalancer.test.js +82 -49
- package/dist/core/Rebalancer.test.js.map +1 -1
- package/dist/core/RebalancerOrchestrator.d.ts +30 -9
- package/dist/core/RebalancerOrchestrator.d.ts.map +1 -1
- package/dist/core/RebalancerOrchestrator.js +79 -71
- package/dist/core/RebalancerOrchestrator.js.map +1 -1
- package/dist/core/RebalancerOrchestrator.test.d.ts +2 -0
- package/dist/core/RebalancerOrchestrator.test.d.ts.map +1 -0
- package/dist/core/RebalancerOrchestrator.test.js +714 -0
- package/dist/core/RebalancerOrchestrator.test.js.map +1 -0
- package/dist/core/RebalancerService.d.ts +7 -3
- package/dist/core/RebalancerService.d.ts.map +1 -1
- package/dist/core/RebalancerService.js +44 -24
- package/dist/core/RebalancerService.js.map +1 -1
- package/dist/core/RebalancerService.test.js +71 -109
- package/dist/core/RebalancerService.test.js.map +1 -1
- package/dist/e2e/collateral-deficit.e2e-test.js +1 -3
- package/dist/e2e/collateral-deficit.e2e-test.js.map +1 -1
- package/dist/e2e/composite.e2e-test.js.map +1 -1
- package/dist/e2e/harness/BridgeSetup.d.ts +6 -0
- package/dist/e2e/harness/BridgeSetup.d.ts.map +1 -1
- package/dist/e2e/harness/BridgeSetup.js +10 -1
- package/dist/e2e/harness/BridgeSetup.js.map +1 -1
- package/dist/e2e/harness/TestHelpers.d.ts.map +1 -1
- package/dist/e2e/harness/TestHelpers.js +1 -4
- package/dist/e2e/harness/TestHelpers.js.map +1 -1
- package/dist/e2e/harness/TestRebalancer.d.ts +1 -1
- package/dist/e2e/harness/TestRebalancer.d.ts.map +1 -1
- package/dist/e2e/harness/TestRebalancer.js +6 -7
- package/dist/e2e/harness/TestRebalancer.js.map +1 -1
- package/dist/e2e/minAmount.e2e-test.js +0 -1
- package/dist/e2e/minAmount.e2e-test.js.map +1 -1
- package/dist/e2e/weighted.e2e-test.js +0 -1
- package/dist/e2e/weighted.e2e-test.js.map +1 -1
- package/dist/factories/RebalancerContextFactory.d.ts +48 -6
- package/dist/factories/RebalancerContextFactory.d.ts.map +1 -1
- package/dist/factories/RebalancerContextFactory.js +170 -17
- package/dist/factories/RebalancerContextFactory.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/IExternalBridge.d.ts +101 -0
- package/dist/interfaces/IExternalBridge.d.ts.map +1 -0
- package/dist/interfaces/IExternalBridge.js +2 -0
- package/dist/interfaces/IExternalBridge.js.map +1 -0
- package/dist/interfaces/IMonitor.d.ts +1 -0
- package/dist/interfaces/IMonitor.d.ts.map +1 -1
- package/dist/interfaces/IRebalancer.d.ts +25 -25
- package/dist/interfaces/IRebalancer.d.ts.map +1 -1
- package/dist/interfaces/IStrategy.d.ts +36 -3
- package/dist/interfaces/IStrategy.d.ts.map +1 -1
- package/dist/interfaces/IStrategy.js +12 -1
- package/dist/interfaces/IStrategy.js.map +1 -1
- package/dist/metrics/PriceGetter.js +1 -1
- package/dist/metrics/PriceGetter.js.map +1 -1
- package/dist/metrics/scripts/metrics.d.ts +3 -3
- package/dist/monitor/Monitor.d.ts +12 -2
- package/dist/monitor/Monitor.d.ts.map +1 -1
- package/dist/monitor/Monitor.js +46 -1
- package/dist/monitor/Monitor.js.map +1 -1
- package/dist/service.js +40 -17
- package/dist/service.js.map +1 -1
- package/dist/strategy/BaseStrategy.d.ts +12 -6
- package/dist/strategy/BaseStrategy.d.ts.map +1 -1
- package/dist/strategy/BaseStrategy.js +56 -21
- package/dist/strategy/BaseStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts +1 -1
- package/dist/strategy/CollateralDeficitStrategy.d.ts.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.js +19 -11
- package/dist/strategy/CollateralDeficitStrategy.js.map +1 -1
- package/dist/strategy/CollateralDeficitStrategy.test.js +135 -2
- package/dist/strategy/CollateralDeficitStrategy.test.js.map +1 -1
- package/dist/strategy/CompositeStrategy.test.js +13 -0
- package/dist/strategy/CompositeStrategy.test.js.map +1 -1
- package/dist/strategy/MinAmountStrategy.test.js +4 -0
- package/dist/strategy/MinAmountStrategy.test.js.map +1 -1
- package/dist/strategy/StrategyFactory.d.ts +2 -1
- package/dist/strategy/StrategyFactory.d.ts.map +1 -1
- package/dist/strategy/StrategyFactory.js +24 -8
- package/dist/strategy/StrategyFactory.js.map +1 -1
- package/dist/strategy/WeightedStrategy.test.js +6 -0
- package/dist/strategy/WeightedStrategy.test.js.map +1 -1
- package/dist/test/helpers.d.ts +8 -7
- package/dist/test/helpers.d.ts.map +1 -1
- package/dist/test/helpers.js +23 -5
- package/dist/test/helpers.js.map +1 -1
- package/dist/test/lifiMocks.d.ts +51 -0
- package/dist/test/lifiMocks.d.ts.map +1 -0
- package/dist/test/lifiMocks.js +130 -0
- package/dist/test/lifiMocks.js.map +1 -0
- package/dist/tracking/ActionTracker.d.ts +33 -1
- package/dist/tracking/ActionTracker.d.ts.map +1 -1
- package/dist/tracking/ActionTracker.js +193 -22
- package/dist/tracking/ActionTracker.js.map +1 -1
- package/dist/tracking/ActionTracker.test.js +107 -19
- package/dist/tracking/ActionTracker.test.js.map +1 -1
- package/dist/tracking/IActionTracker.d.ts +47 -3
- package/dist/tracking/IActionTracker.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.d.ts.map +1 -1
- package/dist/tracking/InflightContextAdapter.js +24 -7
- package/dist/tracking/InflightContextAdapter.js.map +1 -1
- package/dist/tracking/InflightContextAdapter.test.js +7 -4
- package/dist/tracking/InflightContextAdapter.test.js.map +1 -1
- package/dist/tracking/types.d.ts +31 -2
- package/dist/tracking/types.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.d.ts +2 -1
- package/dist/utils/ExplorerClient.d.ts.map +1 -1
- package/dist/utils/ExplorerClient.js +13 -8
- package/dist/utils/ExplorerClient.js.map +1 -1
- package/dist/utils/bridgeUtils.d.ts +27 -4
- package/dist/utils/bridgeUtils.d.ts.map +1 -1
- package/dist/utils/bridgeUtils.js +38 -0
- package/dist/utils/bridgeUtils.js.map +1 -1
- package/dist/utils/bridgeUtils.test.js +9 -0
- package/dist/utils/bridgeUtils.test.js.map +1 -1
- package/dist/utils/gasEstimation.d.ts +65 -0
- package/dist/utils/gasEstimation.d.ts.map +1 -0
- package/dist/utils/gasEstimation.js +176 -0
- package/dist/utils/gasEstimation.js.map +1 -0
- package/dist/utils/tokenUtils.d.ts +9 -1
- package/dist/utils/tokenUtils.d.ts.map +1 -1
- package/dist/utils/tokenUtils.js +11 -0
- package/dist/utils/tokenUtils.js.map +1 -1
- package/package.json +9 -7
- package/src/bridges/LiFiBridge.ts +538 -0
- package/src/config/RebalancerConfig.test.ts +160 -0
- package/src/config/RebalancerConfig.ts +14 -3
- package/src/config/types.ts +136 -10
- package/src/core/InventoryRebalancer.test.ts +1684 -0
- package/src/core/InventoryRebalancer.ts +1255 -0
- package/src/core/Rebalancer.test.ts +84 -30
- package/src/core/Rebalancer.ts +144 -23
- package/src/core/RebalancerOrchestrator.test.ts +860 -0
- package/src/core/RebalancerOrchestrator.ts +146 -95
- package/src/core/RebalancerService.test.ts +80 -123
- package/src/core/RebalancerService.ts +67 -33
- package/src/e2e/collateral-deficit.e2e-test.ts +2 -4
- package/src/e2e/composite.e2e-test.ts +5 -5
- package/src/e2e/harness/BridgeSetup.ts +28 -1
- package/src/e2e/harness/TestHelpers.ts +1 -4
- package/src/e2e/harness/TestRebalancer.ts +7 -7
- package/src/e2e/minAmount.e2e-test.ts +1 -2
- package/src/e2e/weighted.e2e-test.ts +1 -2
- package/src/factories/RebalancerContextFactory.ts +293 -24
- package/src/index.ts +20 -5
- package/src/interfaces/IExternalBridge.ts +115 -0
- package/src/interfaces/IMonitor.ts +1 -0
- package/src/interfaces/IRebalancer.ts +45 -29
- package/src/interfaces/IStrategy.ts +50 -3
- package/src/metrics/PriceGetter.ts +1 -1
- package/src/monitor/Monitor.ts +81 -2
- package/src/service.ts +59 -18
- package/src/strategy/BaseStrategy.ts +77 -24
- package/src/strategy/CollateralDeficitStrategy.test.ts +181 -4
- package/src/strategy/CollateralDeficitStrategy.ts +42 -15
- package/src/strategy/CompositeStrategy.test.ts +13 -0
- package/src/strategy/MinAmountStrategy.test.ts +4 -0
- package/src/strategy/StrategyFactory.ts +33 -6
- package/src/strategy/WeightedStrategy.test.ts +6 -0
- package/src/test/helpers.ts +39 -14
- package/src/test/lifiMocks.ts +174 -0
- package/src/tracking/ActionTracker.test.ts +122 -19
- package/src/tracking/ActionTracker.ts +284 -24
- package/src/tracking/IActionTracker.ts +58 -3
- package/src/tracking/InflightContextAdapter.test.ts +7 -4
- package/src/tracking/InflightContextAdapter.ts +42 -9
- package/src/tracking/types.ts +43 -2
- package/src/utils/ExplorerClient.ts +23 -10
- package/src/utils/bridgeUtils.test.ts +9 -0
- package/src/utils/bridgeUtils.ts +75 -6
- package/src/utils/gasEstimation.ts +272 -0
- package/src/utils/tokenUtils.ts +12 -0
- package/dist/tracking/index.d.ts +0 -7
- package/dist/tracking/index.d.ts.map +0 -1
- package/dist/tracking/index.js +0 -6
- package/dist/tracking/index.js.map +0 -1
- package/dist/utils/index.d.ts +0 -5
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -5
- package/dist/utils/index.js.map +0 -1
- package/src/tracking/index.ts +0 -36
- package/src/utils/index.ts +0 -4
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Logger } from 'pino';
|
|
2
|
+
import type { BridgeQuote, BridgeQuoteParams, BridgeTransferResult, BridgeTransferStatus, ExternalBridgeConfig, IExternalBridge } from '../interfaces/IExternalBridge.js';
|
|
3
|
+
/**
|
|
4
|
+
* LiFi implementation of IExternalBridge using the official @lifi/sdk.
|
|
5
|
+
*
|
|
6
|
+
* The SDK provides:
|
|
7
|
+
* - Automatic token approvals via executeRoute()
|
|
8
|
+
* - Multi-step route handling (swap → bridge → swap)
|
|
9
|
+
* - Built-in status tracking via getStatus()
|
|
10
|
+
* - Native support for EVM, Solana, and other chains
|
|
11
|
+
*
|
|
12
|
+
* @see https://docs.li.fi/integrate-li.fi-sdk
|
|
13
|
+
*/
|
|
14
|
+
export declare class LiFiBridge implements IExternalBridge {
|
|
15
|
+
private static readonly NATIVE_TOKEN_ADDRESS;
|
|
16
|
+
readonly externalBridgeId = "lifi";
|
|
17
|
+
readonly logger: Logger;
|
|
18
|
+
private initialized;
|
|
19
|
+
private readonly config;
|
|
20
|
+
constructor(config: ExternalBridgeConfig, logger: Logger);
|
|
21
|
+
getNativeTokenAddress(): string;
|
|
22
|
+
private initialize;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve RPC URL for a given EVM chainId from chain metadata.
|
|
25
|
+
* Iterates metadata to find matching chainId and returns first HTTP RPC URL.
|
|
26
|
+
*/
|
|
27
|
+
private getRpcUrlForChainId;
|
|
28
|
+
/**
|
|
29
|
+
* Get a quote for bridging tokens.
|
|
30
|
+
* Supports two modes:
|
|
31
|
+
* - fromAmount: "I'm sending X, what do I get?" (uses SDK)
|
|
32
|
+
* - toAmount: "I want X, how much do I send?" (uses REST API)
|
|
33
|
+
*
|
|
34
|
+
* Returns route data ready for execution.
|
|
35
|
+
*/
|
|
36
|
+
quote(params: BridgeQuoteParams): Promise<BridgeQuote>;
|
|
37
|
+
/**
|
|
38
|
+
* Get a quote by specifying the amount to send (standard quote).
|
|
39
|
+
* Uses the LiFi SDK.
|
|
40
|
+
*/
|
|
41
|
+
private quoteBySpendingAmount;
|
|
42
|
+
/**
|
|
43
|
+
* Get a quote by specifying the amount to receive (reverse quote).
|
|
44
|
+
* Uses the LiFi REST API directly since the SDK doesn't support toAmount.
|
|
45
|
+
*/
|
|
46
|
+
private quoteByReceivingAmount;
|
|
47
|
+
/**
|
|
48
|
+
* Extract gas and fee costs from a LiFi quote response.
|
|
49
|
+
* - gasCosts: Sum of all gas costs (transaction fees)
|
|
50
|
+
* - feeCosts: Sum of non-included fee costs (protocol fees not deducted from amount)
|
|
51
|
+
*/
|
|
52
|
+
private extractCosts;
|
|
53
|
+
/**
|
|
54
|
+
* Execute a bridge transfer using the SDK.
|
|
55
|
+
* Handles approvals, transaction signing, and execution automatically.
|
|
56
|
+
*
|
|
57
|
+
* @param quote - Quote obtained from quote()
|
|
58
|
+
* @param privateKey - Private key hex string (0x-prefixed) for signing the transaction
|
|
59
|
+
*/
|
|
60
|
+
execute(quote: BridgeQuote, privateKey: string): Promise<BridgeTransferResult>;
|
|
61
|
+
/**
|
|
62
|
+
* Get the status of a bridge transfer.
|
|
63
|
+
* Uses SDK's built-in status tracking.
|
|
64
|
+
*/
|
|
65
|
+
getStatus(txHash: string, fromChain: number, toChain: number): Promise<BridgeTransferStatus>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=LiFiBridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiFiBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/LiFiBridge.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAKnC,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EAChB,MAAM,kCAAkC,CAAC;AA8E1C;;;;;;;;;;GAUG;AACH,qBAAa,UAAW,YAAW,eAAe;IAChD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CACG;IAE/C,QAAQ,CAAC,gBAAgB,UAAU;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;gBAElC,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;IAKxD,qBAAqB,IAAI,MAAM;IAI/B,OAAO,CAAC,UAAU;IAelB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;;;;;;OAOG;IACG,KAAK,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IAqB5D;;;OAGG;YACW,qBAAqB;IAiDnC;;;OAGG;YACW,sBAAsB;IAoEpC;;;;OAIG;IACH,OAAO,CAAC,YAAY;IA2BpB;;;;;;OAMG;IACG,OAAO,CACX,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,CAAC;IA8HhC;;;OAGG;IACG,SAAS,CACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC;CAiDjC"}
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { EVM, convertQuoteToRoute, createConfig, executeRoute, getQuote, getStatus, config as lifiConfig, } from '@lifi/sdk';
|
|
2
|
+
import { createWalletClient, http } from 'viem';
|
|
3
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
|
+
import { arbitrum, base, mainnet, optimism } from 'viem/chains';
|
|
5
|
+
/**
|
|
6
|
+
* LiFi API base URL for REST endpoints.
|
|
7
|
+
* The SDK doesn't support toAmount quotes, so we use REST API directly.
|
|
8
|
+
*/
|
|
9
|
+
const LIFI_API_BASE = 'https://li.quest/v1';
|
|
10
|
+
/**
|
|
11
|
+
* Known chains for viem - add more as needed.
|
|
12
|
+
* TODO: can we think of a cleaner way to do this?
|
|
13
|
+
*/
|
|
14
|
+
const VIEM_CHAINS = {
|
|
15
|
+
[mainnet.id]: mainnet,
|
|
16
|
+
[arbitrum.id]: arbitrum,
|
|
17
|
+
[base.id]: base,
|
|
18
|
+
[optimism.id]: optimism,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Get viem chain config by chain ID.
|
|
22
|
+
* Falls back to a minimal chain config if not found.
|
|
23
|
+
*/
|
|
24
|
+
function getViemChain(chainId, rpcUrl) {
|
|
25
|
+
const chain = VIEM_CHAINS[chainId];
|
|
26
|
+
if (chain) {
|
|
27
|
+
if (rpcUrl) {
|
|
28
|
+
return { ...chain, rpcUrls: { default: { http: [rpcUrl] } } };
|
|
29
|
+
}
|
|
30
|
+
return chain;
|
|
31
|
+
}
|
|
32
|
+
// Fallback for chains not in our registry
|
|
33
|
+
return {
|
|
34
|
+
id: chainId,
|
|
35
|
+
name: `Chain ${chainId}`,
|
|
36
|
+
nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
|
|
37
|
+
rpcUrls: {
|
|
38
|
+
default: { http: rpcUrl ? [rpcUrl] : [] },
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* LiFi implementation of IExternalBridge using the official @lifi/sdk.
|
|
44
|
+
*
|
|
45
|
+
* The SDK provides:
|
|
46
|
+
* - Automatic token approvals via executeRoute()
|
|
47
|
+
* - Multi-step route handling (swap → bridge → swap)
|
|
48
|
+
* - Built-in status tracking via getStatus()
|
|
49
|
+
* - Native support for EVM, Solana, and other chains
|
|
50
|
+
*
|
|
51
|
+
* @see https://docs.li.fi/integrate-li.fi-sdk
|
|
52
|
+
*/
|
|
53
|
+
export class LiFiBridge {
|
|
54
|
+
static NATIVE_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
|
|
55
|
+
externalBridgeId = 'lifi';
|
|
56
|
+
logger;
|
|
57
|
+
initialized = false;
|
|
58
|
+
config;
|
|
59
|
+
constructor(config, logger) {
|
|
60
|
+
this.config = config;
|
|
61
|
+
this.logger = logger;
|
|
62
|
+
}
|
|
63
|
+
getNativeTokenAddress() {
|
|
64
|
+
return LiFiBridge.NATIVE_TOKEN_ADDRESS;
|
|
65
|
+
}
|
|
66
|
+
initialize() {
|
|
67
|
+
if (this.initialized)
|
|
68
|
+
return;
|
|
69
|
+
createConfig({
|
|
70
|
+
integrator: this.config.integrator,
|
|
71
|
+
apiKey: this.config.apiKey,
|
|
72
|
+
});
|
|
73
|
+
this.initialized = true;
|
|
74
|
+
this.logger.info({ integrator: this.config.integrator }, 'LiFi SDK initialized');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolve RPC URL for a given EVM chainId from chain metadata.
|
|
78
|
+
* Iterates metadata to find matching chainId and returns first HTTP RPC URL.
|
|
79
|
+
*/
|
|
80
|
+
getRpcUrlForChainId(chainId) {
|
|
81
|
+
if (!this.config.chainMetadata)
|
|
82
|
+
return undefined;
|
|
83
|
+
for (const metadata of Object.values(this.config.chainMetadata)) {
|
|
84
|
+
if (metadata.chainId === chainId && metadata.rpcUrls?.length) {
|
|
85
|
+
return metadata.rpcUrls[0].http;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get a quote for bridging tokens.
|
|
92
|
+
* Supports two modes:
|
|
93
|
+
* - fromAmount: "I'm sending X, what do I get?" (uses SDK)
|
|
94
|
+
* - toAmount: "I want X, how much do I send?" (uses REST API)
|
|
95
|
+
*
|
|
96
|
+
* Returns route data ready for execution.
|
|
97
|
+
*/
|
|
98
|
+
async quote(params) {
|
|
99
|
+
this.initialize();
|
|
100
|
+
// Validate that exactly one of fromAmount or toAmount is provided
|
|
101
|
+
if (params.fromAmount !== undefined && params.toAmount !== undefined) {
|
|
102
|
+
throw new Error('Cannot specify both fromAmount and toAmount - provide exactly one');
|
|
103
|
+
}
|
|
104
|
+
if (params.fromAmount === undefined && params.toAmount === undefined) {
|
|
105
|
+
throw new Error('Must specify either fromAmount or toAmount');
|
|
106
|
+
}
|
|
107
|
+
// Dispatch to appropriate quote method
|
|
108
|
+
if (params.toAmount !== undefined) {
|
|
109
|
+
return this.quoteByReceivingAmount(params);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return this.quoteBySpendingAmount(params);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get a quote by specifying the amount to send (standard quote).
|
|
117
|
+
* Uses the LiFi SDK.
|
|
118
|
+
*/
|
|
119
|
+
async quoteBySpendingAmount(params) {
|
|
120
|
+
this.logger.debug({ params }, 'Requesting LiFi quote by spending amount');
|
|
121
|
+
const quote = await getQuote({
|
|
122
|
+
fromChain: params.fromChain,
|
|
123
|
+
toChain: params.toChain,
|
|
124
|
+
fromToken: params.fromToken,
|
|
125
|
+
toToken: params.toToken,
|
|
126
|
+
fromAmount: params.fromAmount.toString(),
|
|
127
|
+
fromAddress: params.fromAddress,
|
|
128
|
+
toAddress: params.toAddress ?? params.fromAddress,
|
|
129
|
+
slippage: params.slippage ?? this.config.defaultSlippage ?? 0.005,
|
|
130
|
+
// Prefer faster routes for rebalancing
|
|
131
|
+
order: 'RECOMMENDED',
|
|
132
|
+
});
|
|
133
|
+
const { gasCosts, feeCosts } = this.extractCosts(quote);
|
|
134
|
+
this.logger.info({
|
|
135
|
+
quoteId: quote.id,
|
|
136
|
+
tool: quote.tool,
|
|
137
|
+
fromAmount: quote.action.fromAmount,
|
|
138
|
+
toAmount: quote.estimate.toAmount,
|
|
139
|
+
toAmountMin: quote.estimate.toAmountMin,
|
|
140
|
+
executionDuration: quote.estimate.executionDuration,
|
|
141
|
+
gasCosts: gasCosts.toString(),
|
|
142
|
+
feeCosts: feeCosts.toString(),
|
|
143
|
+
}, 'LiFi quote received (fromAmount)');
|
|
144
|
+
return {
|
|
145
|
+
id: quote.id,
|
|
146
|
+
tool: quote.tool,
|
|
147
|
+
fromAmount: BigInt(quote.action.fromAmount),
|
|
148
|
+
toAmount: BigInt(quote.estimate.toAmount),
|
|
149
|
+
toAmountMin: BigInt(quote.estimate.toAmountMin),
|
|
150
|
+
executionDuration: quote.estimate.executionDuration,
|
|
151
|
+
gasCosts,
|
|
152
|
+
feeCosts,
|
|
153
|
+
route: quote, // Store full quote for conversion to route
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get a quote by specifying the amount to receive (reverse quote).
|
|
158
|
+
* Uses the LiFi REST API directly since the SDK doesn't support toAmount.
|
|
159
|
+
*/
|
|
160
|
+
async quoteByReceivingAmount(params) {
|
|
161
|
+
this.logger.debug({ params }, 'Requesting LiFi quote by receiving amount');
|
|
162
|
+
const queryParams = new URLSearchParams({
|
|
163
|
+
fromChain: params.fromChain.toString(),
|
|
164
|
+
toChain: params.toChain.toString(),
|
|
165
|
+
fromToken: params.fromToken,
|
|
166
|
+
toToken: params.toToken,
|
|
167
|
+
toAmount: params.toAmount.toString(),
|
|
168
|
+
fromAddress: params.fromAddress,
|
|
169
|
+
toAddress: params.toAddress ?? params.fromAddress,
|
|
170
|
+
slippage: (params.slippage ?? this.config.defaultSlippage ?? 0.005)
|
|
171
|
+
.toFixed(4)
|
|
172
|
+
.replace(/\.?0+$/, ''),
|
|
173
|
+
order: 'CHEAPEST',
|
|
174
|
+
integrator: this.config.integrator,
|
|
175
|
+
});
|
|
176
|
+
if (this.config.apiKey) {
|
|
177
|
+
queryParams.set('apiKey', this.config.apiKey);
|
|
178
|
+
}
|
|
179
|
+
const url = `${LIFI_API_BASE}/quote/toAmount?${queryParams.toString()}`;
|
|
180
|
+
this.logger.debug({ url: url.replace(/apiKey=[^&]+/, 'apiKey=***') }, 'Fetching LiFi toAmount quote');
|
|
181
|
+
const response = await fetch(url);
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
const errorBody = await response.text();
|
|
184
|
+
throw new Error(`LiFi toAmount quote failed: ${response.status} ${response.statusText} - ${errorBody}`);
|
|
185
|
+
}
|
|
186
|
+
const quote = await response.json();
|
|
187
|
+
const { gasCosts, feeCosts } = this.extractCosts(quote);
|
|
188
|
+
this.logger.info({
|
|
189
|
+
quoteId: quote.id,
|
|
190
|
+
tool: quote.tool,
|
|
191
|
+
fromAmount: quote.action.fromAmount,
|
|
192
|
+
toAmount: quote.estimate.toAmount,
|
|
193
|
+
toAmountMin: quote.estimate.toAmountMin,
|
|
194
|
+
executionDuration: quote.estimate.executionDuration,
|
|
195
|
+
gasCosts: gasCosts.toString(),
|
|
196
|
+
feeCosts: feeCosts.toString(),
|
|
197
|
+
}, 'LiFi quote received (toAmount)');
|
|
198
|
+
return {
|
|
199
|
+
id: quote.id,
|
|
200
|
+
tool: quote.tool,
|
|
201
|
+
fromAmount: BigInt(quote.action.fromAmount),
|
|
202
|
+
toAmount: BigInt(quote.estimate.toAmount),
|
|
203
|
+
toAmountMin: BigInt(quote.estimate.toAmountMin),
|
|
204
|
+
executionDuration: quote.estimate.executionDuration,
|
|
205
|
+
gasCosts,
|
|
206
|
+
feeCosts,
|
|
207
|
+
route: quote, // Store full quote for conversion to route
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Extract gas and fee costs from a LiFi quote response.
|
|
212
|
+
* - gasCosts: Sum of all gas costs (transaction fees)
|
|
213
|
+
* - feeCosts: Sum of non-included fee costs (protocol fees not deducted from amount)
|
|
214
|
+
*/
|
|
215
|
+
extractCosts(quote) {
|
|
216
|
+
let gasCosts = 0n;
|
|
217
|
+
let feeCosts = 0n;
|
|
218
|
+
// Sum up gas costs
|
|
219
|
+
if (quote.estimate.gasCosts) {
|
|
220
|
+
for (const cost of quote.estimate.gasCosts) {
|
|
221
|
+
gasCosts += BigInt(cost.amount);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Sum up non-included fee costs
|
|
225
|
+
// (included fees are already deducted from toAmount, so we only count non-included)
|
|
226
|
+
if (quote.estimate.feeCosts) {
|
|
227
|
+
for (const cost of quote.estimate.feeCosts) {
|
|
228
|
+
if (!cost.included) {
|
|
229
|
+
feeCosts += BigInt(cost.amount);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return { gasCosts, feeCosts };
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Execute a bridge transfer using the SDK.
|
|
237
|
+
* Handles approvals, transaction signing, and execution automatically.
|
|
238
|
+
*
|
|
239
|
+
* @param quote - Quote obtained from quote()
|
|
240
|
+
* @param privateKey - Private key hex string (0x-prefixed) for signing the transaction
|
|
241
|
+
*/
|
|
242
|
+
async execute(quote, privateKey) {
|
|
243
|
+
this.initialize();
|
|
244
|
+
// Convert quote to route for execution
|
|
245
|
+
const route = convertQuoteToRoute(quote.route);
|
|
246
|
+
const fromChain = route.fromChainId;
|
|
247
|
+
const toChain = route.toChainId;
|
|
248
|
+
this.logger.info({
|
|
249
|
+
quoteId: quote.id,
|
|
250
|
+
tool: quote.tool,
|
|
251
|
+
fromChain,
|
|
252
|
+
toChain,
|
|
253
|
+
fromAmount: quote.fromAmount.toString(),
|
|
254
|
+
}, 'Executing LiFi bridge transfer');
|
|
255
|
+
// Create viem account and wallet client for the source chain
|
|
256
|
+
const account = privateKeyToAccount(privateKey);
|
|
257
|
+
const rpcUrl = this.getRpcUrlForChainId(fromChain);
|
|
258
|
+
const chain = getViemChain(fromChain, rpcUrl);
|
|
259
|
+
const walletClient = createWalletClient({
|
|
260
|
+
account,
|
|
261
|
+
chain,
|
|
262
|
+
transport: http(rpcUrl),
|
|
263
|
+
});
|
|
264
|
+
this.logger.debug({
|
|
265
|
+
fromChain,
|
|
266
|
+
chainName: chain.name,
|
|
267
|
+
account: account.address,
|
|
268
|
+
}, 'Created viem WalletClient for LiFi execution');
|
|
269
|
+
// Configure LiFi SDK with EVM provider that has our wallet client
|
|
270
|
+
lifiConfig.setProviders([
|
|
271
|
+
EVM({
|
|
272
|
+
getWalletClient: async () => walletClient,
|
|
273
|
+
switchChain: async (requiredChainId) => {
|
|
274
|
+
const switchRpcUrl = this.getRpcUrlForChainId(requiredChainId);
|
|
275
|
+
const requiredChain = getViemChain(requiredChainId, switchRpcUrl);
|
|
276
|
+
return createWalletClient({
|
|
277
|
+
account,
|
|
278
|
+
chain: requiredChain,
|
|
279
|
+
transport: http(switchRpcUrl),
|
|
280
|
+
});
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
]);
|
|
284
|
+
let txHash;
|
|
285
|
+
// Execute route with update callbacks
|
|
286
|
+
const executedRoute = await executeRoute(route, {
|
|
287
|
+
// Update callback for route progress
|
|
288
|
+
updateRouteHook: (updatedRoute) => {
|
|
289
|
+
this.logger.debug({ step: updatedRoute.steps[0]?.id }, 'Route step updated');
|
|
290
|
+
// Extract txHash from execution if available (RouteExtended has LiFiStepExtended with execution)
|
|
291
|
+
const execution = updatedRoute.steps[0]?.execution;
|
|
292
|
+
if (execution?.process) {
|
|
293
|
+
for (const process of execution.process) {
|
|
294
|
+
if (process.txHash) {
|
|
295
|
+
txHash = process.txHash;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
// Auto-accept rate updates for rebalancing
|
|
301
|
+
acceptExchangeRateUpdateHook: async () => true,
|
|
302
|
+
});
|
|
303
|
+
// Extract txHash from executed route if not captured in callbacks
|
|
304
|
+
if (!txHash) {
|
|
305
|
+
const execution = executedRoute.steps[0]?.execution;
|
|
306
|
+
if (execution?.process) {
|
|
307
|
+
for (const process of execution.process) {
|
|
308
|
+
if (process.txHash) {
|
|
309
|
+
txHash = process.txHash;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (!txHash) {
|
|
316
|
+
throw new Error('No transaction hash found in executed route');
|
|
317
|
+
}
|
|
318
|
+
this.logger.info({ txHash, quoteId: quote.id }, 'LiFi bridge transaction executed');
|
|
319
|
+
// Extract transfer ID if available (some bridges provide this)
|
|
320
|
+
let transferId;
|
|
321
|
+
const processes = executedRoute.steps[0]?.execution?.process;
|
|
322
|
+
const txInfo = processes?.find((p) => p.txHash === txHash);
|
|
323
|
+
if (txInfo && 'lifiExplorerLink' in txInfo) {
|
|
324
|
+
// Extract transfer ID from explorer link if available
|
|
325
|
+
const link = txInfo.lifiExplorerLink;
|
|
326
|
+
const match = link?.match(/\/tx\/([^/]+)/);
|
|
327
|
+
if (match) {
|
|
328
|
+
transferId = match[1];
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
txHash,
|
|
333
|
+
fromChain,
|
|
334
|
+
toChain,
|
|
335
|
+
transferId,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Get the status of a bridge transfer.
|
|
340
|
+
* Uses SDK's built-in status tracking.
|
|
341
|
+
*/
|
|
342
|
+
async getStatus(txHash, fromChain, toChain) {
|
|
343
|
+
this.initialize();
|
|
344
|
+
try {
|
|
345
|
+
const status = await getStatus({
|
|
346
|
+
txHash,
|
|
347
|
+
fromChain,
|
|
348
|
+
toChain,
|
|
349
|
+
});
|
|
350
|
+
switch (status.status) {
|
|
351
|
+
case 'DONE': {
|
|
352
|
+
// receiving can be PendingReceivingInfo (only chainId) or ExtendedTransactionInfo (has txHash, amount)
|
|
353
|
+
const receiving = status.receiving;
|
|
354
|
+
const receivingTxHash = receiving && 'txHash' in receiving ? (receiving.txHash ?? '') : '';
|
|
355
|
+
const receivedAmount = receiving && 'amount' in receiving
|
|
356
|
+
? BigInt(receiving.amount ?? '0')
|
|
357
|
+
: BigInt(0);
|
|
358
|
+
return {
|
|
359
|
+
status: 'complete',
|
|
360
|
+
receivingTxHash,
|
|
361
|
+
receivedAmount,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
case 'FAILED':
|
|
365
|
+
return {
|
|
366
|
+
status: 'failed',
|
|
367
|
+
error: status.substatus,
|
|
368
|
+
};
|
|
369
|
+
case 'NOT_FOUND':
|
|
370
|
+
case 'INVALID':
|
|
371
|
+
return { status: 'not_found' };
|
|
372
|
+
case 'PENDING':
|
|
373
|
+
default:
|
|
374
|
+
return {
|
|
375
|
+
status: 'pending',
|
|
376
|
+
substatus: status.substatus,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
this.logger.warn({ txHash, error }, 'Failed to get LiFi status');
|
|
382
|
+
return { status: 'not_found' };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=LiFiBridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiFiBridge.js","sourceRoot":"","sources":["../../src/bridges/LiFiBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import { type ExternalBridgesConfigSchema, type StrategyConfig } from './types.js';
|
|
3
|
+
type ExternalBridgesConfig = z.infer<typeof ExternalBridgesConfigSchema>;
|
|
2
4
|
export declare class RebalancerConfig {
|
|
3
5
|
readonly warpRouteId: string;
|
|
4
6
|
readonly strategyConfig: StrategyConfig[];
|
|
5
|
-
|
|
7
|
+
readonly inventorySigner?: string | undefined;
|
|
8
|
+
readonly externalBridges?: ExternalBridgesConfig | undefined;
|
|
9
|
+
constructor(warpRouteId: string, strategyConfig: StrategyConfig[], inventorySigner?: string | undefined, externalBridges?: ExternalBridgesConfig | undefined);
|
|
6
10
|
/**
|
|
7
11
|
* Loads config from a file
|
|
8
12
|
* @param configFilePath Path to the config file
|
|
9
13
|
*/
|
|
10
14
|
static load(configFilePath: string): RebalancerConfig;
|
|
11
15
|
}
|
|
16
|
+
export {};
|
|
12
17
|
//# sourceMappingURL=RebalancerConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RebalancerConfig.d.ts","sourceRoot":"","sources":["../../src/config/RebalancerConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RebalancerConfig.d.ts","sourceRoot":"","sources":["../../src/config/RebalancerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAK7B,OAAO,EACL,KAAK,2BAA2B,EAGhC,KAAK,cAAc,EAEpB,MAAM,YAAY,CAAC;AAEpB,KAAK,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEzE,qBAAa,gBAAgB;aAET,WAAW,EAAE,MAAM;aACnB,cAAc,EAAE,cAAc,EAAE;aAChC,eAAe,CAAC,EAAE,MAAM;aACxB,eAAe,CAAC,EAAE,qBAAqB;gBAHvC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,cAAc,EAAE,EAChC,eAAe,CAAC,EAAE,MAAM,YAAA,EACxB,eAAe,CAAC,EAAE,qBAAqB,YAAA;IAGzD;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM;CAwBnC"}
|
|
@@ -4,9 +4,13 @@ import { RebalancerConfigSchema, getStrategyChainNames, } from './types.js';
|
|
|
4
4
|
export class RebalancerConfig {
|
|
5
5
|
warpRouteId;
|
|
6
6
|
strategyConfig;
|
|
7
|
-
|
|
7
|
+
inventorySigner;
|
|
8
|
+
externalBridges;
|
|
9
|
+
constructor(warpRouteId, strategyConfig, inventorySigner, externalBridges) {
|
|
8
10
|
this.warpRouteId = warpRouteId;
|
|
9
11
|
this.strategyConfig = strategyConfig;
|
|
12
|
+
this.inventorySigner = inventorySigner;
|
|
13
|
+
this.externalBridges = externalBridges;
|
|
10
14
|
}
|
|
11
15
|
/**
|
|
12
16
|
* Loads config from a file
|
|
@@ -18,13 +22,12 @@ export class RebalancerConfig {
|
|
|
18
22
|
if (!validationResult.success) {
|
|
19
23
|
throw new Error(fromZodError(validationResult.error).message);
|
|
20
24
|
}
|
|
21
|
-
const { warpRouteId, strategy } = validationResult.data;
|
|
22
|
-
// Check that at least one chain is configured across all strategies
|
|
25
|
+
const { warpRouteId, strategy, inventorySigner, externalBridges } = validationResult.data;
|
|
23
26
|
const chainNames = getStrategyChainNames(strategy);
|
|
24
27
|
if (chainNames.length === 0) {
|
|
25
28
|
throw new Error('No chains configured');
|
|
26
29
|
}
|
|
27
|
-
return new RebalancerConfig(warpRouteId, strategy);
|
|
30
|
+
return new RebalancerConfig(warpRouteId, strategy, inventorySigner, externalBridges);
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
//# sourceMappingURL=RebalancerConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RebalancerConfig.js","sourceRoot":"","sources":["../../src/config/RebalancerConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RebalancerConfig.js","sourceRoot":"","sources":["../../src/config/RebalancerConfig.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAGL,sBAAsB,EAEtB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAIpB,MAAM,OAAO,gBAAgB;IAET;IACA;IACA;IACA;IAJlB,YACkB,WAAmB,EACnB,cAAgC,EAChC,eAAwB,EACxB,eAAuC;QAHvC,gBAAW,GAAX,WAAW,CAAQ;QACnB,mBAAc,GAAd,cAAc,CAAkB;QAChC,oBAAe,GAAf,eAAe,CAAS;QACxB,oBAAe,GAAf,eAAe,CAAwB;IACtD,CAAC;IAEJ;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,cAAsB;QAChC,MAAM,MAAM,GAA8B,cAAc,CAAC,cAAc,CAAC,CAAC;QAEzE,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAElE,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,GAC/D,gBAAgB,CAAC,IAAI,CAAC;QAExB,MAAM,UAAU,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,IAAI,gBAAgB,CACzB,WAAW,EACX,QAAQ,EACR,eAAe,EACf,eAAe,CAChB,CAAC;IACJ,CAAC;CACF"}
|