@vultisig/core-chain 2.9.0 → 2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/chains/ton/api.d.ts +11 -0
- package/dist/chains/ton/api.d.ts.map +1 -1
- package/dist/chains/ton/api.js +44 -3
- package/dist/chains/ton/api.js.map +1 -1
- package/dist/coin/token/metadata/chains.d.ts +1 -1
- package/dist/coin/token/metadata/chains.d.ts.map +1 -1
- package/dist/coin/token/metadata/chains.js +1 -0
- package/dist/coin/token/metadata/chains.js.map +1 -1
- package/dist/coin/token/metadata/index.d.ts.map +1 -1
- package/dist/coin/token/metadata/index.js +2 -0
- package/dist/coin/token/metadata/index.js.map +1 -1
- package/dist/coin/token/metadata/resolvers/ton.d.ts +8 -0
- package/dist/coin/token/metadata/resolvers/ton.d.ts.map +1 -0
- package/dist/coin/token/metadata/resolvers/ton.js +10 -0
- package/dist/coin/token/metadata/resolvers/ton.js.map +1 -0
- package/dist/swap/general/cowswap/api/getCowSwapQuote.d.ts.map +1 -1
- package/dist/swap/general/cowswap/api/getCowSwapQuote.js +11 -2
- package/dist/swap/general/cowswap/api/getCowSwapQuote.js.map +1 -1
- package/dist/swap/general/cowswap/getCowSwapExplorerOrderUrl.d.ts +13 -0
- package/dist/swap/general/cowswap/getCowSwapExplorerOrderUrl.d.ts.map +1 -0
- package/dist/swap/general/cowswap/getCowSwapExplorerOrderUrl.js +28 -0
- package/dist/swap/general/cowswap/getCowSwapExplorerOrderUrl.js.map +1 -0
- package/dist/swap/general/cowswap/keysign/cowSwapKeysignData.d.ts +34 -0
- package/dist/swap/general/cowswap/keysign/cowSwapKeysignData.d.ts.map +1 -0
- package/dist/swap/general/cowswap/keysign/cowSwapKeysignData.js +33 -0
- package/dist/swap/general/cowswap/keysign/cowSwapKeysignData.js.map +1 -0
- package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.d.ts +112 -0
- package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.d.ts.map +1 -0
- package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.js +67 -0
- package/dist/swap/general/cowswap/sign/buildCowSwapOrderTypedData.js.map +1 -0
- package/dist/swap/general/lifi/api/getLifiSwapQuote.d.ts +5 -1
- package/dist/swap/general/lifi/api/getLifiSwapQuote.d.ts.map +1 -1
- package/dist/swap/general/lifi/api/getLifiSwapQuote.js +25 -9
- package/dist/swap/general/lifi/api/getLifiSwapQuote.js.map +1 -1
- package/dist/swap/general/lifi/config.d.ts +71 -0
- package/dist/swap/general/lifi/config.d.ts.map +1 -1
- package/dist/swap/general/lifi/config.js +66 -0
- package/dist/swap/general/lifi/config.js.map +1 -1
- package/dist/swap/quote/findSwapQuote.d.ts +9 -10
- package/dist/swap/quote/findSwapQuote.d.ts.map +1 -1
- package/dist/swap/quote/findSwapQuote.js +77 -87
- package/dist/swap/quote/findSwapQuote.js.map +1 -1
- package/dist/utils/getBlockExplorerUrl/index.js +2 -2
- package/dist/utils/getBlockExplorerUrl/index.js.map +1 -1
- package/package.json +21 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LifiAffiliateConfig } from '@vultisig/core-chain/swap/general/lifi/config';
|
|
1
2
|
import { LifiSwapEnabledChain } from '@vultisig/core-chain/swap/general/lifi/LifiSwapEnabledChains';
|
|
2
3
|
import { TransferDirection } from '@vultisig/lib-utils/TransferDirection';
|
|
3
4
|
import { AccountCoinKey } from '../../../../coin/AccountCoin.js';
|
|
@@ -7,6 +8,9 @@ type Input = Record<TransferDirection, AccountCoinKey<LifiSwapEnabledChain> & {
|
|
|
7
8
|
}> & {
|
|
8
9
|
amount: bigint;
|
|
9
10
|
affiliateBps?: number;
|
|
11
|
+
/** Consumer-supplied LI.FI integrator override. When omitted, falls back
|
|
12
|
+
* to the global `lifiConfig.integratorName` (vultisig-0 by default). */
|
|
13
|
+
lifiAffiliateConfig?: LifiAffiliateConfig;
|
|
10
14
|
};
|
|
11
15
|
/** @internal exported for unit tests only */
|
|
12
16
|
export declare const STABLE_TICKERS: ReadonlySet<string>;
|
|
@@ -16,6 +20,6 @@ export declare const isStablePair: (from: {
|
|
|
16
20
|
}, to: {
|
|
17
21
|
ticker?: string;
|
|
18
22
|
}) => boolean;
|
|
19
|
-
export declare const getLifiSwapQuote: ({ amount, affiliateBps, ...transfer }: Input) => Promise<GeneralSwapQuote>;
|
|
23
|
+
export declare const getLifiSwapQuote: ({ amount, affiliateBps, lifiAffiliateConfig, ...transfer }: Input) => Promise<GeneralSwapQuote>;
|
|
20
24
|
export {};
|
|
21
25
|
//# sourceMappingURL=getLifiSwapQuote.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLifiSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getLifiSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAyB,MAAM,+CAA+C,CAAA;AAC1G,OAAO,EAAmB,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AAKpH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAGzD,KAAK,KAAK,GAAG,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,oBAAoB,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG;IACnG,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;4EACwE;IACxE,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;CAC1C,CAAA;AAKD,6CAA6C;AAC7C,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAa7C,CAAA;AAKF,6CAA6C;AAC7C,eAAO,MAAM,YAAY,GAAI,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,OACxB,CAAA;AAkG1D,eAAO,MAAM,gBAAgB,GAAU,4DAKpC,KAAK,KAAG,OAAO,CAAC,gBAAgB,CA8KlC,CAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getQuote } from '@lifi/sdk';
|
|
2
2
|
import { getChainKind } from '@vultisig/core-chain/ChainKind';
|
|
3
3
|
import { solanaConfig } from '@vultisig/core-chain/chains/solana/solanaConfig';
|
|
4
4
|
import { chainFeeCoin } from '@vultisig/core-chain/coin/chainFeeCoin';
|
|
5
|
-
import { lifiConfig } from '@vultisig/core-chain/swap/general/lifi/config';
|
|
5
|
+
import { lifiConfig, setupLifi } from '@vultisig/core-chain/swap/general/lifi/config';
|
|
6
6
|
import { lifiSwapChainId } from '@vultisig/core-chain/swap/general/lifi/LifiSwapEnabledChains';
|
|
7
7
|
import { shouldBePresent } from '@vultisig/lib-utils/assert/shouldBePresent';
|
|
8
8
|
import { match } from '@vultisig/lib-utils/match';
|
|
@@ -30,10 +30,13 @@ export const STABLE_TICKERS = new Set([
|
|
|
30
30
|
const isStableTicker = (ticker) => ticker !== undefined && STABLE_TICKERS.has(ticker.toUpperCase());
|
|
31
31
|
/** @internal exported for unit tests only */
|
|
32
32
|
export const isStablePair = (from, to) => isStableTicker(from.ticker) && isStableTicker(to.ticker);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
/** Lazy bootstrap for callers that never invoked the public `setupLifi`
|
|
34
|
+
* — uses whatever defaults sit on `lifiConfig` (vultisig-0 + no apiUrl
|
|
35
|
+
* unless a consumer mutated them at module load). The public `setupLifi`
|
|
36
|
+
* exported from ../config is idempotent and short-circuits subsequent
|
|
37
|
+
* calls, so this is safe to call on every quote. */
|
|
38
|
+
const ensureLifiConfigured = memoize(() => {
|
|
39
|
+
setupLifi();
|
|
37
40
|
});
|
|
38
41
|
// Slippage tolerance baked into the LiFi-prebuilt swap tx. The
|
|
39
42
|
// returned `transactionRequest.data` is a fully-formed Solana / EVM
|
|
@@ -119,8 +122,8 @@ const resolveSwapFeeChain = (chainId, fallback) => {
|
|
|
119
122
|
}
|
|
120
123
|
return resolved;
|
|
121
124
|
};
|
|
122
|
-
export const getLifiSwapQuote = async ({ amount, affiliateBps, ...transfer }) => {
|
|
123
|
-
|
|
125
|
+
export const getLifiSwapQuote = async ({ amount, affiliateBps, lifiAffiliateConfig, ...transfer }) => {
|
|
126
|
+
ensureLifiConfigured();
|
|
124
127
|
const [fromChain, toChain] = [transfer.from, transfer.to].map(({ chain }) => lifiSwapChainId[chain]);
|
|
125
128
|
const [fromToken, toToken] = [transfer.from, transfer.to].map(({ id, chain }) => id ?? chainFeeCoin[chain].ticker);
|
|
126
129
|
const [fromAddress, toAddress] = [transfer.from, transfer.to].map(({ address }) => address);
|
|
@@ -136,6 +139,12 @@ export const getLifiSwapQuote = async ({ amount, affiliateBps, ...transfer }) =>
|
|
|
136
139
|
if (combinedCostBps > MAX_COMBINED_COST_BPS) {
|
|
137
140
|
console.warn(`[getLifiSwapQuote] affiliate + slippage combined cost exceeds ${MAX_COMBINED_COST_BPS}bps: ${combinedCostBps}bps`);
|
|
138
141
|
}
|
|
142
|
+
// Per-call integrator override — when the consumer supplied a
|
|
143
|
+
// `lifiAffiliateConfig` (e.g. Station via mcp-ts) the affiliate fee
|
|
144
|
+
// for THIS quote is tagged to their portal integrator instead of the
|
|
145
|
+
// SDK-default. Falls back to whatever `lifiConfig.integratorName`
|
|
146
|
+
// resolves to (vultisig-0 unless the consumer's setupLifi() ran first).
|
|
147
|
+
const integrator = lifiAffiliateConfig?.integratorName ?? lifiConfig.integratorName;
|
|
139
148
|
const quote = await getQuote({
|
|
140
149
|
fromChain,
|
|
141
150
|
toChain,
|
|
@@ -144,8 +153,15 @@ export const getLifiSwapQuote = async ({ amount, affiliateBps, ...transfer }) =>
|
|
|
144
153
|
fromAmount: amount.toString(),
|
|
145
154
|
fromAddress,
|
|
146
155
|
toAddress,
|
|
147
|
-
|
|
156
|
+
// NeOMakinG #618 r2 should-fix: explicit `undefined` only when affiliateBps
|
|
157
|
+
// is genuinely unset. `affiliateBps: 0` previously fell into the truthy-test
|
|
158
|
+
// and became `undefined`, which let LiFi's getQuote silently fall back to
|
|
159
|
+
// `_config.routeOptions?.fee` (see @lifi/sdk src/services/api.js: `params.fee
|
|
160
|
+
// ??= _config.routeOptions?.fee`). For a consumer that explicitly set 0,
|
|
161
|
+
// that's a silent non-zero fee. Now: 0 stays 0.
|
|
162
|
+
fee: affiliateBps !== undefined ? affiliateBps / 10000 : undefined,
|
|
148
163
|
slippage,
|
|
164
|
+
integrator,
|
|
149
165
|
});
|
|
150
166
|
const { transactionRequest, estimate } = quote;
|
|
151
167
|
const chainKind = getChainKind(transfer.from.chain);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLifiSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,
|
|
1
|
+
{"version":3,"file":"getLifiSwapQuote.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/swap/general/lifi/api/getLifiSwapQuote.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK-default LI.FI integrator + (optional) API URL. Used when no consumer
|
|
3
|
+
* has called `setupLifi` with a custom config — affiliate fees on routes
|
|
4
|
+
* fetched with these defaults land in the `vultisig-0` portal bucket.
|
|
5
|
+
*
|
|
6
|
+
* Consumers (e.g. Station via vultisig/mcp-ts) override at module boot
|
|
7
|
+
* via `setupLifi({integratorName, apiUrl})` to redirect both the global
|
|
8
|
+
* LI.FI SDK init AND the per-call integrator tag.
|
|
9
|
+
*/
|
|
1
10
|
export declare const lifiConfig: {
|
|
2
11
|
integratorName: string;
|
|
12
|
+
apiUrl: string | undefined;
|
|
3
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Per-CALL affiliate config for LI.FI. Consumer-supplied via
|
|
16
|
+
* `SwapAffiliateConfig.lifi`. Overrides the `integrator` tag on a single
|
|
17
|
+
* `getQuote` request so affiliate fees route to the consumer's LI.FI portal
|
|
18
|
+
* integrator instead of the SDK-default `vultisig-0`.
|
|
19
|
+
*
|
|
20
|
+
* NOTE: this type is INTENTIONALLY narrower than `LifiBootstrapConfig`.
|
|
21
|
+
* LI.FI's `getQuote` API does not accept a per-call `apiUrl` — the base URL
|
|
22
|
+
* is a property of the global SDK init. Including `apiUrl` here would
|
|
23
|
+
* silently mislead consumers who supply `lifi: { integratorName, apiUrl }`
|
|
24
|
+
* via `SwapAffiliateConfig` and expect the proxy to apply: it would not.
|
|
25
|
+
* For the proxy URL, consumers must call `setupLifi({integratorName, apiUrl})`
|
|
26
|
+
* at module boot — see `LifiBootstrapConfig`. (Ehsan-saradar #618 review.)
|
|
27
|
+
*/
|
|
28
|
+
export type LifiAffiliateConfig = {
|
|
29
|
+
integratorName: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Global LI.FI SDK bootstrap config. Strictly wider than `LifiAffiliateConfig`
|
|
33
|
+
* because `apiUrl` is meaningful here (passed to `@lifi/sdk`'s `createConfig`
|
|
34
|
+
* as the base URL for every request the LI.FI SDK makes after this point) and
|
|
35
|
+
* intentionally meaningless on the per-call surface.
|
|
36
|
+
*
|
|
37
|
+
* Consumers call `setupLifi(bootstrap)` once at module boot.
|
|
38
|
+
*/
|
|
39
|
+
export type LifiBootstrapConfig = {
|
|
40
|
+
integratorName: string;
|
|
41
|
+
apiUrl?: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Initialise the global LI.FI SDK config.
|
|
45
|
+
*
|
|
46
|
+
* Two call modes:
|
|
47
|
+
*
|
|
48
|
+
* 1. **Consumer bootstrap** (`setupLifi(config)` with a config arg):
|
|
49
|
+
* Always applies — re-invokes `createConfig` with the supplied
|
|
50
|
+
* integrator + apiUrl regardless of whether a prior lazy default-fallback
|
|
51
|
+
* already ran. This protects against an "ordering footgun" where a swap
|
|
52
|
+
* quote runs before the consumer's boot-time setup and the lazy path
|
|
53
|
+
* silently latches the `vultisig-0` default + drops the consumer's
|
|
54
|
+
* later apiUrl proxy. (Ehsan-saradar #618 review.)
|
|
55
|
+
*
|
|
56
|
+
* 2. **Lazy default** (`setupLifi()` with no arg, called from
|
|
57
|
+
* `ensureLifiConfigured` in `getLifiSwapQuote`): only runs once; idempotent
|
|
58
|
+
* no-op on every subsequent call. Falls back to whatever `lifiConfig`
|
|
59
|
+
* currently holds — `vultisig-0` + no apiUrl unless a consumer mutated
|
|
60
|
+
* them already.
|
|
61
|
+
*
|
|
62
|
+
* Net effect:
|
|
63
|
+
* - Consumer-before-lazy: consumer wins (the only `createConfig` call).
|
|
64
|
+
* - Lazy-before-consumer: lazy installs defaults, then the consumer's
|
|
65
|
+
* explicit call overwrites them via the explicit-bootstrap branch above.
|
|
66
|
+
* - Consumer-after-consumer: the latest consumer-bootstrap call overwrites
|
|
67
|
+
* `lifiConfig` and re-runs `createConfig` (last-writer wins). In practice
|
|
68
|
+
* consumers should only call this once. The `getLifiSwapQuote.integrator`
|
|
69
|
+
* test `'repeated calls re-run createConfig with each new config'` pins
|
|
70
|
+
* this contract. (Ehsan-saradar #618 r2.)
|
|
71
|
+
*/
|
|
72
|
+
export declare const setupLifi: (config?: LifiBootstrapConfig) => void;
|
|
73
|
+
/** @internal Test-only reset hook. Never call from production code. */
|
|
74
|
+
export declare const _resetLifiConfigForTest: () => void;
|
|
4
75
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/lifi/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/lifi/config.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU;;YAEA,MAAM,GAAG,SAAS;CACxC,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,mBAAmB,KAAG,IAmBxD,CAAA;AAED,uEAAuE;AACvE,eAAO,MAAM,uBAAuB,QAAO,IAI1C,CAAA"}
|
|
@@ -1,4 +1,70 @@
|
|
|
1
|
+
import { createConfig } from '@lifi/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* SDK-default LI.FI integrator + (optional) API URL. Used when no consumer
|
|
4
|
+
* has called `setupLifi` with a custom config — affiliate fees on routes
|
|
5
|
+
* fetched with these defaults land in the `vultisig-0` portal bucket.
|
|
6
|
+
*
|
|
7
|
+
* Consumers (e.g. Station via vultisig/mcp-ts) override at module boot
|
|
8
|
+
* via `setupLifi({integratorName, apiUrl})` to redirect both the global
|
|
9
|
+
* LI.FI SDK init AND the per-call integrator tag.
|
|
10
|
+
*/
|
|
1
11
|
export const lifiConfig = {
|
|
2
12
|
integratorName: 'vultisig-0',
|
|
13
|
+
apiUrl: undefined,
|
|
14
|
+
};
|
|
15
|
+
let configured = false;
|
|
16
|
+
/**
|
|
17
|
+
* Initialise the global LI.FI SDK config.
|
|
18
|
+
*
|
|
19
|
+
* Two call modes:
|
|
20
|
+
*
|
|
21
|
+
* 1. **Consumer bootstrap** (`setupLifi(config)` with a config arg):
|
|
22
|
+
* Always applies — re-invokes `createConfig` with the supplied
|
|
23
|
+
* integrator + apiUrl regardless of whether a prior lazy default-fallback
|
|
24
|
+
* already ran. This protects against an "ordering footgun" where a swap
|
|
25
|
+
* quote runs before the consumer's boot-time setup and the lazy path
|
|
26
|
+
* silently latches the `vultisig-0` default + drops the consumer's
|
|
27
|
+
* later apiUrl proxy. (Ehsan-saradar #618 review.)
|
|
28
|
+
*
|
|
29
|
+
* 2. **Lazy default** (`setupLifi()` with no arg, called from
|
|
30
|
+
* `ensureLifiConfigured` in `getLifiSwapQuote`): only runs once; idempotent
|
|
31
|
+
* no-op on every subsequent call. Falls back to whatever `lifiConfig`
|
|
32
|
+
* currently holds — `vultisig-0` + no apiUrl unless a consumer mutated
|
|
33
|
+
* them already.
|
|
34
|
+
*
|
|
35
|
+
* Net effect:
|
|
36
|
+
* - Consumer-before-lazy: consumer wins (the only `createConfig` call).
|
|
37
|
+
* - Lazy-before-consumer: lazy installs defaults, then the consumer's
|
|
38
|
+
* explicit call overwrites them via the explicit-bootstrap branch above.
|
|
39
|
+
* - Consumer-after-consumer: the latest consumer-bootstrap call overwrites
|
|
40
|
+
* `lifiConfig` and re-runs `createConfig` (last-writer wins). In practice
|
|
41
|
+
* consumers should only call this once. The `getLifiSwapQuote.integrator`
|
|
42
|
+
* test `'repeated calls re-run createConfig with each new config'` pins
|
|
43
|
+
* this contract. (Ehsan-saradar #618 r2.)
|
|
44
|
+
*/
|
|
45
|
+
export const setupLifi = (config) => {
|
|
46
|
+
// Consumer-bootstrap branch — always applies, regardless of `configured`.
|
|
47
|
+
if (config) {
|
|
48
|
+
lifiConfig.integratorName = config.integratorName;
|
|
49
|
+
lifiConfig.apiUrl = config.apiUrl;
|
|
50
|
+
createConfig(config.apiUrl
|
|
51
|
+
? { integrator: config.integratorName, apiUrl: config.apiUrl }
|
|
52
|
+
: { integrator: config.integratorName });
|
|
53
|
+
configured = true;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Lazy default branch — idempotent.
|
|
57
|
+
if (configured)
|
|
58
|
+
return;
|
|
59
|
+
const integrator = lifiConfig.integratorName;
|
|
60
|
+
const apiUrl = lifiConfig.apiUrl;
|
|
61
|
+
createConfig(apiUrl ? { integrator, apiUrl } : { integrator });
|
|
62
|
+
configured = true;
|
|
63
|
+
};
|
|
64
|
+
/** @internal Test-only reset hook. Never call from production code. */
|
|
65
|
+
export const _resetLifiConfigForTest = () => {
|
|
66
|
+
configured = false;
|
|
67
|
+
lifiConfig.integratorName = 'vultisig-0';
|
|
68
|
+
lifiConfig.apiUrl = undefined;
|
|
3
69
|
};
|
|
4
70
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/lifi/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,cAAc,EAAE,YAAY;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/swap/general/lifi/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,cAAc,EAAE,YAAY;IAC5B,MAAM,EAAE,SAA+B;CACxC,CAAA;AAiCD,IAAI,UAAU,GAAG,KAAK,CAAA;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAA4B,EAAQ,EAAE;IAC9D,0EAA0E;IAC1E,IAAI,MAAM,EAAE,CAAC;QACX,UAAU,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAA;QACjD,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;QACjC,YAAY,CACV,MAAM,CAAC,MAAM;YACX,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAC9D,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE,CAC1C,CAAA;QACD,UAAU,GAAG,IAAI,CAAA;QACjB,OAAM;IACR,CAAC;IACD,oCAAoC;IACpC,IAAI,UAAU;QAAE,OAAM;IACtB,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,CAAA;IAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAA;IAChC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;IAC9D,UAAU,GAAG,IAAI,CAAA;AACnB,CAAC,CAAA;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAS,EAAE;IAChD,UAAU,GAAG,KAAK,CAAA;IAClB,UAAU,CAAC,cAAc,GAAG,YAAY,CAAA;IACxC,UAAU,CAAC,MAAM,GAAG,SAAS,CAAA;AAC/B,CAAC,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AccountCoin } from '@vultisig/core-chain/coin/AccountCoin';
|
|
2
2
|
import { VultDiscountTier } from '@vultisig/core-chain/swap/affiliate';
|
|
3
3
|
import { KyberSwapBaseAffiliateConfig } from '@vultisig/core-chain/swap/general/kyber/config';
|
|
4
|
+
import { LifiAffiliateConfig } from '@vultisig/core-chain/swap/general/lifi/config';
|
|
4
5
|
import { OneInchAffiliateConfig } from '@vultisig/core-chain/swap/general/oneInch/api/getOneInchSwapQuote';
|
|
5
6
|
import { NativeSwapAffiliateConfig } from '@vultisig/core-chain/swap/native/api/affiliate';
|
|
6
7
|
import { TransferDirection } from '@vultisig/lib-utils/TransferDirection';
|
|
@@ -14,6 +15,7 @@ export type SwapAffiliateConfig = {
|
|
|
14
15
|
native?: NativeSwapAffiliateConfig;
|
|
15
16
|
oneInch?: OneInchAffiliateConfig;
|
|
16
17
|
kyber?: KyberSwapBaseAffiliateConfig;
|
|
18
|
+
lifi?: LifiAffiliateConfig;
|
|
17
19
|
};
|
|
18
20
|
export type FindSwapQuoteInput = Record<TransferDirection, AccountCoin> & {
|
|
19
21
|
amount: bigint;
|
|
@@ -23,19 +25,16 @@ export type FindSwapQuoteInput = Record<TransferDirection, AccountCoin> & {
|
|
|
23
25
|
};
|
|
24
26
|
type SwapQuoteProviderName = 'CowSwap' | 'KyberSwap' | '1inch' | 'LiFi' | 'SwapKit' | 'THORChain' | 'MayaChain';
|
|
25
27
|
/**
|
|
26
|
-
* Declared preference order for
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* because they have hard priority over aggregators regardless of output.
|
|
32
|
-
*
|
|
33
|
-
* Order rationale: KyberSwap and 1inch typically surface the best on-chain
|
|
34
|
-
* liquidity for EVM-only swaps; LiFi covers the broader cross-chain matrix;
|
|
35
|
-
* SwapKit is the catch-all fallback. Adjust as data changes.
|
|
28
|
+
* Declared preference order for economically equivalent quotes. Quotes are
|
|
29
|
+
* first ranked by comparable net output across all providers. Providers within
|
|
30
|
+
* `SWAP_QUOTE_PREFERENCE_BAND_BPS` of the best output are then selected by this
|
|
31
|
+
* order, so users stay close to the best rate while near-ties prefer CowSwap,
|
|
32
|
+
* native routes, and SwapKit economics.
|
|
36
33
|
*
|
|
37
34
|
* @internal Exported for unit-test introspection only.
|
|
38
35
|
*/
|
|
36
|
+
export declare const providerPreferenceOrder: readonly SwapQuoteProviderName[];
|
|
37
|
+
/** @deprecated Use `providerPreferenceOrder`. */
|
|
39
38
|
export declare const aggregatorPreferenceOrder: readonly SwapQuoteProviderName[];
|
|
40
39
|
export declare const findSwapQuote: ({ from, to, amount, referral, vultDiscountTier, affiliateConfig, }: FindSwapQuoteInput) => Promise<SwapQuote>;
|
|
41
40
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/quote/findSwapQuote.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAuB,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAM3F,OAAO,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAA;
|
|
1
|
+
{"version":3,"file":"findSwapQuote.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/swap/quote/findSwapQuote.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAuB,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAM3F,OAAO,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAA;AAE7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAA;AAEnF,OAAO,EAEL,sBAAsB,EACvB,MAAM,mEAAmE,CAAA;AAQ1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAA;AAe1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAEzE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC;;;;8CAI8C;AAC9C,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,yBAAyB,CAAA;IAClC,OAAO,CAAC,EAAE,sBAAsB,CAAA;IAChC,KAAK,CAAC,EAAE,4BAA4B,CAAA;IACpC,IAAI,CAAC,EAAE,mBAAmB,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,GAAG;IACxE,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC1C,eAAe,CAAC,EAAE,mBAAmB,CAAA;CACtC,CAAA;AAED,KAAK,qBAAqB,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAA;AAyB/G;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,qBAAqB,EAY1D,CAAA;AAEV,iDAAiD;AACjD,eAAO,MAAM,yBAAyB,kCAA0B,CAAA;AA4FhE,eAAO,MAAM,aAAa,GAAU,oEAOjC,kBAAkB,KAAG,OAAO,CAAC,SAAS,CAsYxC,CAAA"}
|
|
@@ -23,34 +23,6 @@ import { isOneOf } from '@vultisig/lib-utils/array/isOneOf';
|
|
|
23
23
|
import { bigIntToNumber } from '@vultisig/lib-utils/bigint/bigIntToNumber';
|
|
24
24
|
import { isInError } from '@vultisig/lib-utils/error/isInError';
|
|
25
25
|
import { pick } from '@vultisig/lib-utils/record/pick';
|
|
26
|
-
/**
|
|
27
|
-
* Hard native priority: when any direct THORChain or MayaChain route is available,
|
|
28
|
-
* it is always preferred over any aggregator (SwapKit, LiFi, etc.) regardless of
|
|
29
|
-
* gross output. When both THOR and Maya succeed, the one with the higher comparable
|
|
30
|
-
* output wins; among aggregator-only results the normal output ranking applies.
|
|
31
|
-
*
|
|
32
|
-
* Rationale (paaao, 2026-05-22): for L1 swaps that native protocols serve directly,
|
|
33
|
-
* the protocol-aligned route is always preferred. Direct routes capture full
|
|
34
|
-
* vultisig affiliate revenue and avoid the aggregator fee skim; the protocol is
|
|
35
|
-
* the moat. Mirrors the priority-first-success pattern in vultisig-ios's
|
|
36
|
-
* `SwapService.fetchQuote` + `Coin+Swaps.swapProviders`.
|
|
37
|
-
*/
|
|
38
|
-
/**
|
|
39
|
-
* Native swap providers — direct on-chain protocols (no aggregator layer).
|
|
40
|
-
*
|
|
41
|
-
* Adding a new native protocol (e.g. Chainflip-direct in the future) requires:
|
|
42
|
-
* 1. Adding its name to `SwapQuoteProviderName` above
|
|
43
|
-
* 2. Adding it here so `isNativeProvider` recognises it for hard-priority
|
|
44
|
-
* selection in `selectBestEligibleQuote`
|
|
45
|
-
* 3. Wiring its fetcher into `getNativeFetchers`
|
|
46
|
-
*
|
|
47
|
-
* The `satisfies` clause gives compile-time safety against typos, but the
|
|
48
|
-
* semantic mapping (which providers count as "native") still lives in this
|
|
49
|
-
* file and must be kept aligned with the protocol's actual integration mode.
|
|
50
|
-
*/
|
|
51
|
-
const nativeProviderNames = ['THORChain', 'MayaChain'];
|
|
52
|
-
const nativeProviderNamesSet = new Set(nativeProviderNames);
|
|
53
|
-
const isNativeProvider = (name) => nativeProviderNamesSet.has(name);
|
|
54
26
|
const QUOTE_FETCH_TIMEOUT_MS = 30_000;
|
|
55
27
|
const withTimeout = (p, ms) => {
|
|
56
28
|
let timeoutId;
|
|
@@ -62,30 +34,38 @@ const withTimeout = (p, ms) => {
|
|
|
62
34
|
});
|
|
63
35
|
};
|
|
64
36
|
/**
|
|
65
|
-
* Declared preference order for
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* because they have hard priority over aggregators regardless of output.
|
|
71
|
-
*
|
|
72
|
-
* Order rationale: KyberSwap and 1inch typically surface the best on-chain
|
|
73
|
-
* liquidity for EVM-only swaps; LiFi covers the broader cross-chain matrix;
|
|
74
|
-
* SwapKit is the catch-all fallback. Adjust as data changes.
|
|
37
|
+
* Declared preference order for economically equivalent quotes. Quotes are
|
|
38
|
+
* first ranked by comparable net output across all providers. Providers within
|
|
39
|
+
* `SWAP_QUOTE_PREFERENCE_BAND_BPS` of the best output are then selected by this
|
|
40
|
+
* order, so users stay close to the best rate while near-ties prefer CowSwap,
|
|
41
|
+
* native routes, and SwapKit economics.
|
|
75
42
|
*
|
|
76
43
|
* @internal Exported for unit-test introspection only.
|
|
77
44
|
*/
|
|
78
|
-
export const
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
45
|
+
export const providerPreferenceOrder = [
|
|
46
|
+
// CowSwap is slotted FIRST: its solver-driven RFQ fills are MEV-protected and
|
|
47
|
+
// gas-less, so on an exact-output tie it is the preferred route. It only
|
|
48
|
+
// competes for same-chain ERC-20 EVM pairs (see fetcher registration below);
|
|
49
|
+
// for every other pair it simply isn't in the candidate set.
|
|
50
|
+
'CowSwap',
|
|
51
|
+
'THORChain',
|
|
52
|
+
'MayaChain',
|
|
53
|
+
'SwapKit',
|
|
82
54
|
'KyberSwap',
|
|
83
55
|
'1inch',
|
|
84
56
|
'LiFi',
|
|
85
|
-
'SwapKit',
|
|
86
57
|
];
|
|
87
|
-
|
|
88
|
-
const
|
|
58
|
+
/** @deprecated Use `providerPreferenceOrder`. */
|
|
59
|
+
export const aggregatorPreferenceOrder = providerPreferenceOrder;
|
|
60
|
+
const providerPreferenceIndex = new Map(providerPreferenceOrder.map((name, idx) => [name, idx]));
|
|
61
|
+
const getProviderPreferenceRank = (name) => providerPreferenceIndex.get(name) ?? Number.POSITIVE_INFINITY;
|
|
62
|
+
/**
|
|
63
|
+
* Tuning point for issue #605's banded routing rule. 100 bps = 1%.
|
|
64
|
+
* Adjust this when product wants a wider or narrower provider-preference band.
|
|
65
|
+
*/
|
|
66
|
+
const SWAP_QUOTE_PREFERENCE_BAND_BPS = 100n;
|
|
67
|
+
const BPS_DENOMINATOR = 10000n;
|
|
68
|
+
const isWithinPreferenceBand = (outputAmount, bestOutputAmount) => outputAmount * BPS_DENOMINATOR >= bestOutputAmount * (BPS_DENOMINATOR - SWAP_QUOTE_PREFERENCE_BAND_BPS);
|
|
89
69
|
/** Re-base an integer amount from `fromDecimals` fixed-point to `toDecimals`. */
|
|
90
70
|
function rebaseDecimals(value, fromDecimals, toDecimals) {
|
|
91
71
|
if (fromDecimals === toDecimals) {
|
|
@@ -117,40 +97,32 @@ function getComparableOutputAmount(q, to) {
|
|
|
117
97
|
return BigInt(q.quote.general.dstAmount);
|
|
118
98
|
}
|
|
119
99
|
function selectBestEligibleQuote(settled) {
|
|
120
|
-
|
|
121
|
-
let bestAggregator = null;
|
|
122
|
-
let bestAggregatorPreferenceRank = Number.POSITIVE_INFINITY;
|
|
100
|
+
const candidates = [];
|
|
123
101
|
for (let i = 0; i < settled.length; i++) {
|
|
124
102
|
const result = settled[i];
|
|
125
|
-
if (result.status
|
|
126
|
-
|
|
103
|
+
if (result.status === 'fulfilled') {
|
|
104
|
+
candidates.push(result.value);
|
|
127
105
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
106
|
+
}
|
|
107
|
+
if (candidates.length === 0) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const bestOutputAmount = candidates.reduce((best, candidate) => (candidate.outputAmount > best ? candidate.outputAmount : best), candidates[0].outputAmount);
|
|
111
|
+
let selected = null;
|
|
112
|
+
let selectedPreferenceRank = Number.POSITIVE_INFINITY;
|
|
113
|
+
for (const candidate of candidates) {
|
|
114
|
+
if (!isWithinPreferenceBand(candidate.outputAmount, bestOutputAmount)) {
|
|
115
|
+
continue;
|
|
134
116
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const candidateRank = getAggregatorPreferenceRank(candidate.providerName);
|
|
142
|
-
if (bestAggregator === null ||
|
|
143
|
-
candidate.outputAmount > bestAggregator.outputAmount ||
|
|
144
|
-
(candidate.outputAmount === bestAggregator.outputAmount && candidateRank < bestAggregatorPreferenceRank)) {
|
|
145
|
-
bestAggregator = candidate;
|
|
146
|
-
bestAggregatorPreferenceRank = candidateRank;
|
|
147
|
-
}
|
|
117
|
+
const candidatePreferenceRank = getProviderPreferenceRank(candidate.providerName);
|
|
118
|
+
if (selected === null ||
|
|
119
|
+
candidatePreferenceRank < selectedPreferenceRank ||
|
|
120
|
+
(candidatePreferenceRank === selectedPreferenceRank && candidate.outputAmount > selected.outputAmount)) {
|
|
121
|
+
selected = candidate;
|
|
122
|
+
selectedPreferenceRank = candidatePreferenceRank;
|
|
148
123
|
}
|
|
149
124
|
}
|
|
150
|
-
|
|
151
|
-
// over any aggregator route. Mirrors vultisig-ios's priority-first-success
|
|
152
|
-
// pattern. No output comparison between native and aggregator.
|
|
153
|
-
return (bestNative ?? bestAggregator)?.quote ?? null;
|
|
125
|
+
return selected?.quote ?? null;
|
|
154
126
|
}
|
|
155
127
|
export const findSwapQuote = async ({ from, to, amount, referral, vultDiscountTier, affiliateConfig, }) => {
|
|
156
128
|
// Runtime guard: THORName affiliateFeeAddress must be lowercase.
|
|
@@ -193,19 +165,36 @@ export const findSwapQuote = async ({ from, to, amount, referral, vultDiscountTi
|
|
|
193
165
|
const fromChain = from.chain;
|
|
194
166
|
const toChain = to.chain;
|
|
195
167
|
const chainAmount = amount;
|
|
196
|
-
// CowSwap
|
|
197
|
-
//
|
|
198
|
-
// `
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
168
|
+
// CowSwap (Phase 2 — off-chain RFQ orders). Gated to same-chain ERC-20 →
|
|
169
|
+
// ERC-20 pairs on a CowSwap-supported EVM chain. Both sides must be ERC-20
|
|
170
|
+
// (`from.id` and `to.id` present): selling native ETH needs the GPv2
|
|
171
|
+
// eth-flow contract (out of scope here) and the off-chain order is settled
|
|
172
|
+
// by solvers against ERC-20 balances. The consumer signs the order's
|
|
173
|
+
// EIP-712 digest and submits it via `submitCowSwapOrder` — see
|
|
174
|
+
// `cowswap_order` handling in `buildSwapKeysignPayload`.
|
|
175
|
+
if (fromChain === toChain &&
|
|
176
|
+
isOneOf(fromChain, cowSwapSupportedChains) &&
|
|
177
|
+
from.id !== undefined &&
|
|
178
|
+
to.id !== undefined) {
|
|
179
|
+
const cowChainConfig = cowSwapChainConfig[fromChain];
|
|
180
|
+
const sellToken = from.id;
|
|
181
|
+
const buyToken = to.id;
|
|
182
|
+
result.push({
|
|
183
|
+
providerName: 'CowSwap',
|
|
184
|
+
fetch: async () => {
|
|
185
|
+
const general = await getCowSwapQuote({
|
|
186
|
+
sellToken,
|
|
187
|
+
buyToken,
|
|
188
|
+
sellAmount: chainAmount,
|
|
189
|
+
from: from.address,
|
|
190
|
+
receiver: from.address,
|
|
191
|
+
chainConfig: cowChainConfig,
|
|
192
|
+
affiliateBps,
|
|
193
|
+
});
|
|
194
|
+
return { quote: { general }, discounts: vultDiscount };
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
209
198
|
if (isOneOf(fromChain, kyberSwapEnabledChains) &&
|
|
210
199
|
isOneOf(toChain, kyberSwapEnabledChains) &&
|
|
211
200
|
fromChain === toChain) {
|
|
@@ -260,6 +249,7 @@ export const findSwapQuote = async ({ from, to, amount, referral, vultDiscountTi
|
|
|
260
249
|
},
|
|
261
250
|
amount: chainAmount,
|
|
262
251
|
affiliateBps,
|
|
252
|
+
lifiAffiliateConfig: affiliateConfig?.lifi,
|
|
263
253
|
});
|
|
264
254
|
return { quote: { general }, discounts: vultDiscount };
|
|
265
255
|
},
|
|
@@ -345,7 +335,7 @@ export const findSwapQuote = async ({ from, to, amount, referral, vultDiscountTi
|
|
|
345
335
|
// deterministic message selection regardless of `Promise.allSettled`
|
|
346
336
|
// resolution order. (#535 r3 — NeO preferably-blocking response.)
|
|
347
337
|
const belowMinimumProviderOrder = [
|
|
348
|
-
|
|
338
|
+
'CowSwap',
|
|
349
339
|
'KyberSwap',
|
|
350
340
|
'1inch',
|
|
351
341
|
'LiFi',
|