@luxfi/dex 1.2.1 → 1.3.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/client/clob.d.ts +52 -0
- package/dist/client/clob.d.ts.map +1 -0
- package/dist/client/clob.js +196 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/types.d.ts +126 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +5 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/use-quote.d.ts +18 -0
- package/dist/hooks/use-quote.d.ts.map +1 -0
- package/dist/hooks/use-quote.js +65 -0
- package/dist/hooks/use-swap.d.ts +17 -0
- package/dist/hooks/use-swap.d.ts.map +1 -0
- package/dist/hooks/use-swap.js +75 -0
- package/dist/index.d.ts +33 -115
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -225
- package/dist/precompile/abis.d.ts +400 -0
- package/dist/precompile/abis.d.ts.map +1 -0
- package/dist/precompile/abis.js +287 -0
- package/dist/precompile/addresses.d.ts +65 -0
- package/dist/precompile/addresses.d.ts.map +1 -0
- package/dist/precompile/addresses.js +52 -0
- package/dist/precompile/index.d.ts +8 -0
- package/dist/precompile/index.d.ts.map +1 -0
- package/dist/precompile/index.js +7 -0
- package/dist/precompile/types.d.ts +76 -0
- package/dist/precompile/types.d.ts.map +1 -0
- package/dist/precompile/types.js +17 -0
- package/dist/router/index.d.ts +7 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +6 -0
- package/dist/router/router.d.ts +58 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +272 -0
- package/dist/router/types.d.ts +76 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +1 -0
- package/package.json +55 -29
- package/src/client/clob.ts +256 -0
- package/src/client/index.ts +6 -0
- package/src/client/types.ts +148 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/use-quote.ts +92 -0
- package/src/hooks/use-swap.ts +103 -0
- package/src/index.ts +76 -309
- package/src/precompile/abis.ts +291 -0
- package/src/precompile/addresses.ts +72 -0
- package/src/precompile/index.ts +7 -0
- package/src/precompile/types.ts +96 -0
- package/src/router/index.ts +6 -0
- package/src/router/router.ts +338 -0
- package/src/router/types.ts +87 -0
- package/dist/marketData.d.ts +0 -152
- package/dist/marketData.d.ts.map +0 -1
- package/dist/marketData.js +0 -253
- package/src/marketData.ts +0 -351
- package/tsconfig.json +0 -19
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DEX Precompile Addresses
|
|
3
|
+
* Native Go implementation at EVM level
|
|
4
|
+
*
|
|
5
|
+
* Lux Precompile Address Standard:
|
|
6
|
+
* - Prefix format: 0xNNNN000000000000000000000000000000000000
|
|
7
|
+
* - Range 0x0400-0x04FF is reserved for DEX precompiles
|
|
8
|
+
*
|
|
9
|
+
* @see ~/work/lux/precompile/dex/module.go for implementation
|
|
10
|
+
*/
|
|
11
|
+
import type { Address } from 'viem';
|
|
12
|
+
/**
|
|
13
|
+
* DEX Precompile contract addresses
|
|
14
|
+
* These are native precompiles, not deployed contracts
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEX_PRECOMPILES: {
|
|
17
|
+
/**
|
|
18
|
+
* PoolManager (0x0400)
|
|
19
|
+
* Singleton managing all liquidity pools
|
|
20
|
+
* - Initialize pools
|
|
21
|
+
* - Execute swaps
|
|
22
|
+
* - Modify liquidity
|
|
23
|
+
* - Flash accounting settlement
|
|
24
|
+
*/
|
|
25
|
+
readonly POOL_MANAGER: Address;
|
|
26
|
+
/**
|
|
27
|
+
* SwapRouter (0x0401)
|
|
28
|
+
* Optimized swap routing
|
|
29
|
+
* - exactInputSingle / exactOutputSingle
|
|
30
|
+
* - Multi-hop swaps
|
|
31
|
+
* - Native LUX support
|
|
32
|
+
*/
|
|
33
|
+
readonly SWAP_ROUTER: Address;
|
|
34
|
+
/**
|
|
35
|
+
* HooksRegistry (0x0402)
|
|
36
|
+
* Hook contract registry
|
|
37
|
+
* - Register hook contracts
|
|
38
|
+
* - Query hook permissions
|
|
39
|
+
*/
|
|
40
|
+
readonly HOOKS_REGISTRY: Address;
|
|
41
|
+
/**
|
|
42
|
+
* FlashLoan (0x0403)
|
|
43
|
+
* Flash loan facility
|
|
44
|
+
* - Borrow any token
|
|
45
|
+
* - Repay in same transaction
|
|
46
|
+
*/
|
|
47
|
+
readonly FLASH_LOAN: Address;
|
|
48
|
+
/**
|
|
49
|
+
* Lending (0x0410)
|
|
50
|
+
* Lending protocol
|
|
51
|
+
*/
|
|
52
|
+
readonly LENDING: Address;
|
|
53
|
+
/**
|
|
54
|
+
* Liquid (0x0430)
|
|
55
|
+
* Liquid staking vaults
|
|
56
|
+
*/
|
|
57
|
+
readonly LIQUID: Address;
|
|
58
|
+
/**
|
|
59
|
+
* Teleport (0x0440)
|
|
60
|
+
* Cross-chain bridge
|
|
61
|
+
*/
|
|
62
|
+
readonly TELEPORT: Address;
|
|
63
|
+
};
|
|
64
|
+
export type DexPrecompile = keyof typeof DEX_PRECOMPILES;
|
|
65
|
+
//# sourceMappingURL=addresses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addresses.d.ts","sourceRoot":"","sources":["../../src/precompile/addresses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;;;;OAOG;2BAC2D,OAAO;IAErE;;;;;;OAMG;0BAC0D,OAAO;IAEpE;;;;;OAKG;6BAC6D,OAAO;IAEvE;;;;;OAKG;yBACyD,OAAO;IAEnE;;;OAGG;sBACsD,OAAO;IAEhE;;;OAGG;qBACqD,OAAO;IAE/D;;;OAGG;uBACuD,OAAO;CACzD,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,eAAe,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DEX Precompile contract addresses
|
|
3
|
+
* These are native precompiles, not deployed contracts
|
|
4
|
+
*/
|
|
5
|
+
export const DEX_PRECOMPILES = {
|
|
6
|
+
/**
|
|
7
|
+
* PoolManager (0x0400)
|
|
8
|
+
* Singleton managing all liquidity pools
|
|
9
|
+
* - Initialize pools
|
|
10
|
+
* - Execute swaps
|
|
11
|
+
* - Modify liquidity
|
|
12
|
+
* - Flash accounting settlement
|
|
13
|
+
*/
|
|
14
|
+
POOL_MANAGER: '0x0400000000000000000000000000000000000000',
|
|
15
|
+
/**
|
|
16
|
+
* SwapRouter (0x0401)
|
|
17
|
+
* Optimized swap routing
|
|
18
|
+
* - exactInputSingle / exactOutputSingle
|
|
19
|
+
* - Multi-hop swaps
|
|
20
|
+
* - Native LUX support
|
|
21
|
+
*/
|
|
22
|
+
SWAP_ROUTER: '0x0401000000000000000000000000000000000000',
|
|
23
|
+
/**
|
|
24
|
+
* HooksRegistry (0x0402)
|
|
25
|
+
* Hook contract registry
|
|
26
|
+
* - Register hook contracts
|
|
27
|
+
* - Query hook permissions
|
|
28
|
+
*/
|
|
29
|
+
HOOKS_REGISTRY: '0x0402000000000000000000000000000000000000',
|
|
30
|
+
/**
|
|
31
|
+
* FlashLoan (0x0403)
|
|
32
|
+
* Flash loan facility
|
|
33
|
+
* - Borrow any token
|
|
34
|
+
* - Repay in same transaction
|
|
35
|
+
*/
|
|
36
|
+
FLASH_LOAN: '0x0403000000000000000000000000000000000000',
|
|
37
|
+
/**
|
|
38
|
+
* Lending (0x0410)
|
|
39
|
+
* Lending protocol
|
|
40
|
+
*/
|
|
41
|
+
LENDING: '0x0410000000000000000000000000000000000000',
|
|
42
|
+
/**
|
|
43
|
+
* Liquid (0x0430)
|
|
44
|
+
* Liquid staking vaults
|
|
45
|
+
*/
|
|
46
|
+
LIQUID: '0x0430000000000000000000000000000000000000',
|
|
47
|
+
/**
|
|
48
|
+
* Teleport (0x0440)
|
|
49
|
+
* Cross-chain bridge
|
|
50
|
+
*/
|
|
51
|
+
TELEPORT: '0x0440000000000000000000000000000000000000',
|
|
52
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/precompile/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DEX Precompile Types
|
|
3
|
+
* Native Uniswap v4-style AMM implementation
|
|
4
|
+
*/
|
|
5
|
+
import type { Address } from 'viem';
|
|
6
|
+
/**
|
|
7
|
+
* Currency type - address(0) = native LUX
|
|
8
|
+
*/
|
|
9
|
+
export interface Currency {
|
|
10
|
+
address: Address;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Pool key uniquely identifies a pool
|
|
14
|
+
*/
|
|
15
|
+
export interface PoolKey {
|
|
16
|
+
currency0: Address;
|
|
17
|
+
currency1: Address;
|
|
18
|
+
fee: number;
|
|
19
|
+
tickSpacing: number;
|
|
20
|
+
hooks: Address;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Balance delta from swap/liquidity operations
|
|
24
|
+
* Positive = user owes pool, Negative = pool owes user
|
|
25
|
+
*/
|
|
26
|
+
export interface BalanceDelta {
|
|
27
|
+
amount0: bigint;
|
|
28
|
+
amount1: bigint;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Swap parameters
|
|
32
|
+
*/
|
|
33
|
+
export interface SwapParams {
|
|
34
|
+
zeroForOne: boolean;
|
|
35
|
+
amountSpecified: bigint;
|
|
36
|
+
sqrtPriceLimitX96: bigint;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Modify liquidity parameters
|
|
40
|
+
*/
|
|
41
|
+
export interface ModifyLiquidityParams {
|
|
42
|
+
tickLower: number;
|
|
43
|
+
tickUpper: number;
|
|
44
|
+
liquidityDelta: bigint;
|
|
45
|
+
salt: `0x${string}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Pool state
|
|
49
|
+
*/
|
|
50
|
+
export interface PoolState {
|
|
51
|
+
sqrtPriceX96: bigint;
|
|
52
|
+
tick: number;
|
|
53
|
+
protocolFee: number;
|
|
54
|
+
lpFee: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Position info
|
|
58
|
+
*/
|
|
59
|
+
export interface Position {
|
|
60
|
+
liquidity: bigint;
|
|
61
|
+
feeGrowthInside0LastX128: bigint;
|
|
62
|
+
feeGrowthInside1LastX128: bigint;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Native LUX currency constant
|
|
66
|
+
*/
|
|
67
|
+
export declare const NATIVE_LUX: Address;
|
|
68
|
+
/**
|
|
69
|
+
* Sort currencies for pool key creation
|
|
70
|
+
*/
|
|
71
|
+
export declare function sortCurrencies(a: Address, b: Address): [Address, Address];
|
|
72
|
+
/**
|
|
73
|
+
* Create a pool key from two currencies
|
|
74
|
+
*/
|
|
75
|
+
export declare function createPoolKey(tokenA: Address, tokenB: Address, fee?: number, tickSpacing?: number, hooks?: Address): PoolKey;
|
|
76
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/precompile/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,OAAO,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,KAAK,MAAM,EAAE,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,wBAAwB,EAAE,MAAM,CAAA;IAChC,wBAAwB,EAAE,MAAM,CAAA;CACjC;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,OAAsD,CAAA;AAE/E;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAEzE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,OAAO,EACf,GAAG,GAAE,MAAa,EAClB,WAAW,GAAE,MAAW,EACxB,KAAK,GAAE,OAAsD,GAC5D,OAAO,CAGT"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native LUX currency constant
|
|
3
|
+
*/
|
|
4
|
+
export const NATIVE_LUX = '0x0000000000000000000000000000000000000000';
|
|
5
|
+
/**
|
|
6
|
+
* Sort currencies for pool key creation
|
|
7
|
+
*/
|
|
8
|
+
export function sortCurrencies(a, b) {
|
|
9
|
+
return a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create a pool key from two currencies
|
|
13
|
+
*/
|
|
14
|
+
export function createPoolKey(tokenA, tokenB, fee = 3000, tickSpacing = 60, hooks = '0x0000000000000000000000000000000000000000') {
|
|
15
|
+
const [currency0, currency1] = sortCurrencies(tokenA, tokenB);
|
|
16
|
+
return { currency0, currency1, fee, tickSpacing, hooks };
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Omnichain Router
|
|
3
|
+
* Routes orders between CLOB and AMM for best execution
|
|
4
|
+
*/
|
|
5
|
+
import type { PublicClient } from 'viem';
|
|
6
|
+
import type { ICLOBClient } from '../client/types';
|
|
7
|
+
import type { RouterConfig, QuoteRequest, Quote, SwapRequest, SwapResult } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Omnichain Router
|
|
10
|
+
* Best execution routing between CLOB and AMM
|
|
11
|
+
*/
|
|
12
|
+
export declare class OmnichainRouter {
|
|
13
|
+
private config;
|
|
14
|
+
private publicClient;
|
|
15
|
+
private clobClient;
|
|
16
|
+
constructor(config?: Partial<RouterConfig>);
|
|
17
|
+
/**
|
|
18
|
+
* Set the public client for AMM interactions
|
|
19
|
+
*/
|
|
20
|
+
setPublicClient(client: PublicClient): void;
|
|
21
|
+
/**
|
|
22
|
+
* Set the CLOB client
|
|
23
|
+
*/
|
|
24
|
+
setCLOBClient(client: ICLOBClient): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get a quote for a swap
|
|
27
|
+
*/
|
|
28
|
+
getQuote(request: QuoteRequest): Promise<Quote>;
|
|
29
|
+
/**
|
|
30
|
+
* Get AMM quote using precompiles
|
|
31
|
+
*/
|
|
32
|
+
private getAMMQuote;
|
|
33
|
+
/**
|
|
34
|
+
* Get CLOB quote
|
|
35
|
+
*/
|
|
36
|
+
private getCLOBQuote;
|
|
37
|
+
/**
|
|
38
|
+
* Convert token addresses to trading symbol
|
|
39
|
+
*/
|
|
40
|
+
private getSymbol;
|
|
41
|
+
/**
|
|
42
|
+
* Execute a swap
|
|
43
|
+
*/
|
|
44
|
+
executeSwap(request: SwapRequest): Promise<SwapResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Execute AMM swap via precompile
|
|
47
|
+
*/
|
|
48
|
+
private executeAMMSwap;
|
|
49
|
+
/**
|
|
50
|
+
* Execute CLOB swap
|
|
51
|
+
*/
|
|
52
|
+
private executeCLOBSwap;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create an omnichain router instance
|
|
56
|
+
*/
|
|
57
|
+
export declare function createRouter(config?: Partial<RouterConfig>): OmnichainRouter;
|
|
58
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,MAAM,CAAA;AAIjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,KAAK,EAEL,WAAW,EACX,UAAU,EACX,MAAM,SAAS,CAAA;AAUhB;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,UAAU,CAA2B;gBAEjC,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAI9C;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,YAAY;IAIpC;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,WAAW;IAIjC;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;IAkDrD;;OAEG;YACW,WAAW;IAgEzB;;OAEG;YACW,YAAY;IAwE1B;;OAEG;IACH,OAAO,CAAC,SAAS;IAgBjB;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAmB5D;;OAEG;YACW,cAAc;IAU5B;;OAEG;YACW,eAAe;CAyB9B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,eAAe,CAE5E"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { DEX_PRECOMPILES } from '../precompile/addresses';
|
|
2
|
+
import { POOL_MANAGER_ABI } from '../precompile/abis';
|
|
3
|
+
import { createPoolKey } from '../precompile/types';
|
|
4
|
+
const DEFAULT_CONFIG = {
|
|
5
|
+
clobEnabled: true,
|
|
6
|
+
ammEnabled: true,
|
|
7
|
+
maxHops: 3,
|
|
8
|
+
preferCLOB: false,
|
|
9
|
+
hybridEnabled: true,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Omnichain Router
|
|
13
|
+
* Best execution routing between CLOB and AMM
|
|
14
|
+
*/
|
|
15
|
+
export class OmnichainRouter {
|
|
16
|
+
config;
|
|
17
|
+
publicClient = null;
|
|
18
|
+
clobClient = null;
|
|
19
|
+
constructor(config = {}) {
|
|
20
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Set the public client for AMM interactions
|
|
24
|
+
*/
|
|
25
|
+
setPublicClient(client) {
|
|
26
|
+
this.publicClient = client;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Set the CLOB client
|
|
30
|
+
*/
|
|
31
|
+
setCLOBClient(client) {
|
|
32
|
+
this.clobClient = client;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get a quote for a swap
|
|
36
|
+
*/
|
|
37
|
+
async getQuote(request) {
|
|
38
|
+
const { tokenIn, tokenOut, amountIn, slippageTolerance = 50, // 0.5%
|
|
39
|
+
preferredSource, } = request;
|
|
40
|
+
const quotes = [];
|
|
41
|
+
// Get AMM quote if enabled
|
|
42
|
+
if (this.config.ammEnabled && (!preferredSource || preferredSource !== 'clob')) {
|
|
43
|
+
try {
|
|
44
|
+
const ammQuote = await this.getAMMQuote(tokenIn, tokenOut, amountIn);
|
|
45
|
+
if (ammQuote)
|
|
46
|
+
quotes.push(ammQuote);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.warn('AMM quote failed:', error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Get CLOB quote if enabled
|
|
53
|
+
if (this.config.clobEnabled && this.clobClient && (!preferredSource || preferredSource !== 'amm')) {
|
|
54
|
+
try {
|
|
55
|
+
const clobQuote = await this.getCLOBQuote(tokenIn, tokenOut, amountIn);
|
|
56
|
+
if (clobQuote)
|
|
57
|
+
quotes.push(clobQuote);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.warn('CLOB quote failed:', error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (quotes.length === 0) {
|
|
64
|
+
throw new Error('No quotes available');
|
|
65
|
+
}
|
|
66
|
+
// Select best quote (highest output)
|
|
67
|
+
const bestQuote = quotes.reduce((best, quote) => quote.amountOut > best.amountOut ? quote : best);
|
|
68
|
+
// Apply slippage tolerance
|
|
69
|
+
const minimumAmountOut = bestQuote.amountOut - (bestQuote.amountOut * BigInt(slippageTolerance)) / 10000n;
|
|
70
|
+
return {
|
|
71
|
+
...bestQuote,
|
|
72
|
+
minimumAmountOut,
|
|
73
|
+
validUntil: Date.now() + 30000, // 30 seconds
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get AMM quote using precompiles
|
|
78
|
+
*/
|
|
79
|
+
async getAMMQuote(tokenIn, tokenOut, amountIn) {
|
|
80
|
+
if (!this.publicClient)
|
|
81
|
+
return null;
|
|
82
|
+
try {
|
|
83
|
+
// Create pool key
|
|
84
|
+
const poolKey = createPoolKey(tokenIn, tokenOut);
|
|
85
|
+
const zeroForOne = tokenIn.toLowerCase() < tokenOut.toLowerCase();
|
|
86
|
+
// Get pool state
|
|
87
|
+
const slot0 = await this.publicClient.readContract({
|
|
88
|
+
address: DEX_PRECOMPILES.POOL_MANAGER,
|
|
89
|
+
abi: POOL_MANAGER_ABI,
|
|
90
|
+
functionName: 'getSlot0',
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
+
args: [poolKey],
|
|
93
|
+
});
|
|
94
|
+
if (slot0[0] === 0n) {
|
|
95
|
+
return null; // Pool doesn't exist
|
|
96
|
+
}
|
|
97
|
+
// Calculate expected output (simplified - real implementation would use tick math)
|
|
98
|
+
// For now, use a simple estimate based on sqrt price
|
|
99
|
+
const sqrtPriceX96 = slot0[0];
|
|
100
|
+
const price = (sqrtPriceX96 * sqrtPriceX96) / (2n ** 192n);
|
|
101
|
+
const amountOut = zeroForOne
|
|
102
|
+
? (amountIn * price) / (10n ** 18n)
|
|
103
|
+
: (amountIn * (10n ** 18n)) / price;
|
|
104
|
+
// Estimate price impact (simplified)
|
|
105
|
+
const priceImpact = Number((amountIn * 10n) / (amountIn + amountOut));
|
|
106
|
+
const step = {
|
|
107
|
+
source: 'amm',
|
|
108
|
+
tokenIn,
|
|
109
|
+
tokenOut,
|
|
110
|
+
amountIn,
|
|
111
|
+
amountOut,
|
|
112
|
+
pool: DEX_PRECOMPILES.POOL_MANAGER,
|
|
113
|
+
fee: (amountIn * BigInt(poolKey.fee)) / 1000000n,
|
|
114
|
+
priceImpact,
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
tokenIn,
|
|
118
|
+
tokenOut,
|
|
119
|
+
amountIn,
|
|
120
|
+
amountOut,
|
|
121
|
+
minimumAmountOut: amountOut,
|
|
122
|
+
route: [step],
|
|
123
|
+
priceImpact,
|
|
124
|
+
estimatedGas: 150000n,
|
|
125
|
+
validUntil: Date.now() + 30000,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.error('AMM quote error:', error);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get CLOB quote
|
|
135
|
+
*/
|
|
136
|
+
async getCLOBQuote(tokenIn, tokenOut, amountIn) {
|
|
137
|
+
if (!this.clobClient || !this.clobClient.isConnected())
|
|
138
|
+
return null;
|
|
139
|
+
try {
|
|
140
|
+
// Convert addresses to symbol (e.g., "LUX-USDT")
|
|
141
|
+
const symbol = this.getSymbol(tokenIn, tokenOut);
|
|
142
|
+
if (!symbol)
|
|
143
|
+
return null;
|
|
144
|
+
const orderBook = await this.clobClient.getOrderBook(symbol, 50);
|
|
145
|
+
// Calculate output by walking the order book
|
|
146
|
+
let remainingIn = amountIn;
|
|
147
|
+
let totalOut = 0n;
|
|
148
|
+
const side = tokenIn.toLowerCase() < tokenOut.toLowerCase() ? 'asks' : 'bids';
|
|
149
|
+
const levels = side === 'asks' ? orderBook.asks : orderBook.bids;
|
|
150
|
+
for (const level of levels) {
|
|
151
|
+
if (remainingIn <= 0n)
|
|
152
|
+
break;
|
|
153
|
+
const levelSize = BigInt(Math.floor(level.size * 1e18));
|
|
154
|
+
const levelPrice = BigInt(Math.floor(level.price * 1e18));
|
|
155
|
+
const fillSize = remainingIn < levelSize ? remainingIn : levelSize;
|
|
156
|
+
const fillOut = side === 'asks'
|
|
157
|
+
? (fillSize * (10n ** 18n)) / levelPrice
|
|
158
|
+
: (fillSize * levelPrice) / (10n ** 18n);
|
|
159
|
+
totalOut += fillOut;
|
|
160
|
+
remainingIn -= fillSize;
|
|
161
|
+
}
|
|
162
|
+
if (totalOut === 0n)
|
|
163
|
+
return null;
|
|
164
|
+
// Calculate price impact
|
|
165
|
+
const avgPrice = (amountIn * (10n ** 18n)) / totalOut;
|
|
166
|
+
const bestPrice = BigInt(Math.floor(levels[0]?.price * 1e18 || 0));
|
|
167
|
+
const priceImpact = bestPrice > 0n
|
|
168
|
+
? Number(((avgPrice - bestPrice) * 10000n) / bestPrice)
|
|
169
|
+
: 0;
|
|
170
|
+
const step = {
|
|
171
|
+
source: 'clob',
|
|
172
|
+
tokenIn,
|
|
173
|
+
tokenOut,
|
|
174
|
+
amountIn,
|
|
175
|
+
amountOut: totalOut,
|
|
176
|
+
symbol,
|
|
177
|
+
fee: (amountIn * 30n) / 10000n, // 0.3% maker fee estimate
|
|
178
|
+
priceImpact,
|
|
179
|
+
};
|
|
180
|
+
return {
|
|
181
|
+
tokenIn,
|
|
182
|
+
tokenOut,
|
|
183
|
+
amountIn,
|
|
184
|
+
amountOut: totalOut,
|
|
185
|
+
minimumAmountOut: totalOut,
|
|
186
|
+
route: [step],
|
|
187
|
+
priceImpact,
|
|
188
|
+
estimatedGas: 50000n, // CLOB is off-chain
|
|
189
|
+
validUntil: Date.now() + 10000, // 10 seconds (faster expiry for CLOB)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
console.error('CLOB quote error:', error);
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Convert token addresses to trading symbol
|
|
199
|
+
*/
|
|
200
|
+
getSymbol(tokenIn, tokenOut) {
|
|
201
|
+
// TODO: Implement proper token-to-symbol mapping
|
|
202
|
+
// This should look up the token registry
|
|
203
|
+
const tokenMap = {
|
|
204
|
+
'0x0000000000000000000000000000000000000000': 'LUX',
|
|
205
|
+
// Add more tokens as needed
|
|
206
|
+
};
|
|
207
|
+
const symbolIn = tokenMap[tokenIn.toLowerCase()];
|
|
208
|
+
const symbolOut = tokenMap[tokenOut.toLowerCase()];
|
|
209
|
+
if (!symbolIn || !symbolOut)
|
|
210
|
+
return null;
|
|
211
|
+
return `${symbolIn}-${symbolOut}`;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Execute a swap
|
|
215
|
+
*/
|
|
216
|
+
async executeSwap(request) {
|
|
217
|
+
const { quote, recipient, deadline = Math.floor(Date.now() / 1000) + 1200 } = request;
|
|
218
|
+
if (Date.now() > quote.validUntil) {
|
|
219
|
+
throw new Error('Quote expired');
|
|
220
|
+
}
|
|
221
|
+
// Determine execution path
|
|
222
|
+
const source = quote.route[0]?.source;
|
|
223
|
+
if (source === 'amm') {
|
|
224
|
+
return this.executeAMMSwap(quote, recipient, deadline);
|
|
225
|
+
}
|
|
226
|
+
else if (source === 'clob') {
|
|
227
|
+
return this.executeCLOBSwap(quote, recipient);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
throw new Error(`Unknown route source: ${source}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Execute AMM swap via precompile
|
|
235
|
+
*/
|
|
236
|
+
async executeAMMSwap(quote, recipient, deadline) {
|
|
237
|
+
// This would be called by the wallet/wagmi on the frontend
|
|
238
|
+
// Just return the transaction parameters
|
|
239
|
+
throw new Error('AMM swap execution should be handled by wagmi writeContract');
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Execute CLOB swap
|
|
243
|
+
*/
|
|
244
|
+
async executeCLOBSwap(quote, recipient) {
|
|
245
|
+
if (!this.clobClient) {
|
|
246
|
+
throw new Error('CLOB client not configured');
|
|
247
|
+
}
|
|
248
|
+
const step = quote.route[0];
|
|
249
|
+
if (!step?.symbol) {
|
|
250
|
+
throw new Error('Invalid CLOB route');
|
|
251
|
+
}
|
|
252
|
+
// Place market order on CLOB
|
|
253
|
+
const order = await this.clobClient.placeOrder({
|
|
254
|
+
symbol: step.symbol,
|
|
255
|
+
side: step.tokenIn.toLowerCase() < step.tokenOut.toLowerCase() ? 'buy' : 'sell',
|
|
256
|
+
type: 'market',
|
|
257
|
+
size: Number(quote.amountIn) / 1e18,
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
txHash: `0x${order.orderId}`,
|
|
261
|
+
amountIn: quote.amountIn,
|
|
262
|
+
amountOut: quote.amountOut,
|
|
263
|
+
route: quote.route,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Create an omnichain router instance
|
|
269
|
+
*/
|
|
270
|
+
export function createRouter(config) {
|
|
271
|
+
return new OmnichainRouter(config);
|
|
272
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Types
|
|
3
|
+
* Types for hybrid CLOB + AMM routing
|
|
4
|
+
*/
|
|
5
|
+
import type { Address } from 'viem';
|
|
6
|
+
/**
|
|
7
|
+
* Route source - where liquidity comes from
|
|
8
|
+
*/
|
|
9
|
+
export type RouteSource = 'clob' | 'amm' | 'hybrid';
|
|
10
|
+
/**
|
|
11
|
+
* Quote request
|
|
12
|
+
*/
|
|
13
|
+
export interface QuoteRequest {
|
|
14
|
+
tokenIn: Address;
|
|
15
|
+
tokenOut: Address;
|
|
16
|
+
amountIn: bigint;
|
|
17
|
+
slippageTolerance?: number;
|
|
18
|
+
preferredSource?: RouteSource;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Route step
|
|
22
|
+
*/
|
|
23
|
+
export interface RouteStep {
|
|
24
|
+
source: RouteSource;
|
|
25
|
+
tokenIn: Address;
|
|
26
|
+
tokenOut: Address;
|
|
27
|
+
amountIn: bigint;
|
|
28
|
+
amountOut: bigint;
|
|
29
|
+
pool?: Address;
|
|
30
|
+
symbol?: string;
|
|
31
|
+
fee: bigint;
|
|
32
|
+
priceImpact: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Quote response
|
|
36
|
+
*/
|
|
37
|
+
export interface Quote {
|
|
38
|
+
tokenIn: Address;
|
|
39
|
+
tokenOut: Address;
|
|
40
|
+
amountIn: bigint;
|
|
41
|
+
amountOut: bigint;
|
|
42
|
+
minimumAmountOut: bigint;
|
|
43
|
+
route: RouteStep[];
|
|
44
|
+
priceImpact: number;
|
|
45
|
+
estimatedGas: bigint;
|
|
46
|
+
validUntil: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Swap request
|
|
50
|
+
*/
|
|
51
|
+
export interface SwapRequest {
|
|
52
|
+
quote: Quote;
|
|
53
|
+
recipient: Address;
|
|
54
|
+
deadline?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Swap result
|
|
58
|
+
*/
|
|
59
|
+
export interface SwapResult {
|
|
60
|
+
txHash: `0x${string}`;
|
|
61
|
+
amountIn: bigint;
|
|
62
|
+
amountOut: bigint;
|
|
63
|
+
route: RouteStep[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Router configuration
|
|
67
|
+
*/
|
|
68
|
+
export interface RouterConfig {
|
|
69
|
+
clobUrl?: string;
|
|
70
|
+
clobEnabled?: boolean;
|
|
71
|
+
ammEnabled?: boolean;
|
|
72
|
+
maxHops?: number;
|
|
73
|
+
preferCLOB?: boolean;
|
|
74
|
+
hybridEnabled?: boolean;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/router/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;AAEnD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,eAAe,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,SAAS,EAAE,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAE3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;IAGrB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAGhB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|