@luxfi/exchange 0.1.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/bridge/__tests__/use-private-teleport.test.d.ts +2 -0
- package/dist/bridge/__tests__/use-private-teleport.test.d.ts.map +1 -0
- package/dist/bridge/__tests__/use-private-teleport.test.js +272 -0
- package/dist/bridge/cross-chain-store.d.ts +57 -0
- package/dist/bridge/cross-chain-store.d.ts.map +1 -0
- package/dist/bridge/cross-chain-store.js +158 -0
- package/dist/bridge/index.d.ts +78 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +79 -0
- package/dist/bridge/private-teleport-types.d.ts +634 -0
- package/dist/bridge/private-teleport-types.d.ts.map +1 -0
- package/dist/bridge/private-teleport-types.js +308 -0
- package/dist/bridge/types.d.ts +84 -0
- package/dist/bridge/types.d.ts.map +1 -0
- package/dist/bridge/types.js +37 -0
- package/dist/bridge/use-cross-chain-mint.d.ts +34 -0
- package/dist/bridge/use-cross-chain-mint.d.ts.map +1 -0
- package/dist/bridge/use-cross-chain-mint.js +228 -0
- package/dist/bridge/use-private-teleport.d.ts +69 -0
- package/dist/bridge/use-private-teleport.d.ts.map +1 -0
- package/dist/bridge/use-private-teleport.js +666 -0
- package/dist/chains/index.d.ts +6 -0
- package/dist/chains/index.d.ts.map +1 -0
- package/dist/chains/index.js +6 -0
- package/dist/chains/lux.d.ts +508 -0
- package/dist/chains/lux.d.ts.map +1 -0
- package/dist/chains/lux.js +131 -0
- package/dist/contracts/abis/dex-swap-router.d.ts +137 -0
- package/dist/contracts/abis/dex-swap-router.d.ts.map +1 -0
- package/dist/contracts/abis/dex-swap-router.js +95 -0
- package/dist/contracts/abis/erc20.d.ts +136 -0
- package/dist/contracts/abis/erc20.d.ts.map +1 -0
- package/dist/contracts/abis/erc20.js +96 -0
- package/dist/contracts/abis/index.d.ts +15 -0
- package/dist/contracts/abis/index.d.ts.map +1 -0
- package/dist/contracts/abis/index.js +15 -0
- package/dist/contracts/abis/nft-position-manager.d.ts +235 -0
- package/dist/contracts/abis/nft-position-manager.d.ts.map +1 -0
- package/dist/contracts/abis/nft-position-manager.js +146 -0
- package/dist/contracts/abis/pool-manager.d.ts +315 -0
- package/dist/contracts/abis/pool-manager.d.ts.map +1 -0
- package/dist/contracts/abis/pool-manager.js +191 -0
- package/dist/contracts/abis/quoter-v2.d.ts +103 -0
- package/dist/contracts/abis/quoter-v2.d.ts.map +1 -0
- package/dist/contracts/abis/quoter-v2.js +68 -0
- package/dist/contracts/abis/swap-router.d.ts +119 -0
- package/dist/contracts/abis/swap-router.d.ts.map +1 -0
- package/dist/contracts/abis/swap-router.js +75 -0
- package/dist/contracts/abis/uniswap-v2-factory.d.ts +75 -0
- package/dist/contracts/abis/uniswap-v2-factory.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v2-factory.js +49 -0
- package/dist/contracts/abis/uniswap-v2-pair.d.ts +119 -0
- package/dist/contracts/abis/uniswap-v2-pair.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v2-pair.js +85 -0
- package/dist/contracts/abis/uniswap-v2-router.d.ts +249 -0
- package/dist/contracts/abis/uniswap-v2-router.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v2-router.js +146 -0
- package/dist/contracts/abis/uniswap-v3-factory.d.ts +77 -0
- package/dist/contracts/abis/uniswap-v3-factory.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v3-factory.js +45 -0
- package/dist/contracts/abis/uniswap-v3-pool.d.ts +128 -0
- package/dist/contracts/abis/uniswap-v3-pool.d.ts.map +1 -0
- package/dist/contracts/abis/uniswap-v3-pool.js +81 -0
- package/dist/contracts/addresses.d.ts +141 -0
- package/dist/contracts/addresses.d.ts.map +1 -0
- package/dist/contracts/addresses.js +108 -0
- package/dist/contracts/index.d.ts +6 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +5 -0
- package/dist/dex/balance-delta.d.ts +27 -0
- package/dist/dex/balance-delta.d.ts.map +1 -0
- package/dist/dex/balance-delta.js +45 -0
- package/dist/dex/index.d.ts +7 -0
- package/dist/dex/index.d.ts.map +1 -0
- package/dist/dex/index.js +6 -0
- package/dist/dex/pool-key.d.ts +19 -0
- package/dist/dex/pool-key.d.ts.map +1 -0
- package/dist/dex/pool-key.js +44 -0
- package/dist/dex/types.d.ts +71 -0
- package/dist/dex/types.d.ts.map +1 -0
- package/dist/dex/types.js +28 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +9 -0
- package/dist/hooks/use-pools.d.ts +24 -0
- package/dist/hooks/use-pools.d.ts.map +1 -0
- package/dist/hooks/use-pools.js +85 -0
- package/dist/hooks/use-positions.d.ts +17 -0
- package/dist/hooks/use-positions.d.ts.map +1 -0
- package/dist/hooks/use-positions.js +65 -0
- package/dist/hooks/use-swap-quote.d.ts +19 -0
- package/dist/hooks/use-swap-quote.d.ts.map +1 -0
- package/dist/hooks/use-swap-quote.js +54 -0
- package/dist/hooks/use-swap.d.ts +22 -0
- package/dist/hooks/use-swap.d.ts.map +1 -0
- package/dist/hooks/use-swap.js +46 -0
- package/dist/hooks/use-token-allowance.d.ts +27 -0
- package/dist/hooks/use-token-allowance.d.ts.map +1 -0
- package/dist/hooks/use-token-allowance.js +59 -0
- package/dist/hooks/use-token-balance.d.ts +17 -0
- package/dist/hooks/use-token-balance.d.ts.map +1 -0
- package/dist/hooks/use-token-balance.js +58 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/stores/index.d.ts +7 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +6 -0
- package/dist/stores/settings-store.d.ts +25 -0
- package/dist/stores/settings-store.d.ts.map +1 -0
- package/dist/stores/settings-store.js +16 -0
- package/dist/stores/swap-store.d.ts +38 -0
- package/dist/stores/swap-store.d.ts.map +1 -0
- package/dist/stores/swap-store.js +58 -0
- package/dist/stores/token-store.d.ts +21 -0
- package/dist/stores/token-store.d.ts.map +1 -0
- package/dist/stores/token-store.js +32 -0
- package/dist/tokens/index.d.ts +65 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +185 -0
- package/package.json +78 -0
- package/src/chains/index.ts +21 -0
- package/src/chains/lux.ts +141 -0
- package/src/contracts/abis/dex-swap-router.ts +98 -0
- package/src/contracts/abis/erc20.ts +96 -0
- package/src/contracts/abis/index.ts +17 -0
- package/src/contracts/abis/nft-position-manager.ts +146 -0
- package/src/contracts/abis/pool-manager.ts +198 -0
- package/src/contracts/abis/quoter-v2.ts +68 -0
- package/src/contracts/abis/swap-router.ts +75 -0
- package/src/contracts/abis/uniswap-v2-factory.ts +49 -0
- package/src/contracts/abis/uniswap-v2-pair.ts +85 -0
- package/src/contracts/abis/uniswap-v2-router.ts +146 -0
- package/src/contracts/abis/uniswap-v3-factory.ts +45 -0
- package/src/contracts/abis/uniswap-v3-pool.ts +81 -0
- package/src/contracts/addresses.ts +128 -0
- package/src/contracts/index.ts +14 -0
- package/src/dex/balance-delta.ts +52 -0
- package/src/dex/index.ts +7 -0
- package/src/dex/pool-key.ts +62 -0
- package/src/dex/types.ts +87 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/use-pools.ts +116 -0
- package/src/hooks/use-positions.ts +90 -0
- package/src/hooks/use-swap-quote.ts +81 -0
- package/src/hooks/use-swap.ts +64 -0
- package/src/hooks/use-token-allowance.ts +74 -0
- package/src/hooks/use-token-balance.ts +71 -0
- package/src/index.ts +31 -0
- package/src/stores/index.ts +7 -0
- package/src/stores/settings-store.ts +54 -0
- package/src/stores/swap-store.ts +112 -0
- package/src/stores/token-store.ts +62 -0
- package/src/tokens/index.ts +220 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UniswapV3Pool ABI (essential functions)
|
|
3
|
+
*/
|
|
4
|
+
export const UNISWAP_V3_POOL_ABI = [
|
|
5
|
+
{
|
|
6
|
+
type: 'function',
|
|
7
|
+
name: 'token0',
|
|
8
|
+
inputs: [],
|
|
9
|
+
outputs: [{ type: 'address' }],
|
|
10
|
+
stateMutability: 'view',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
type: 'function',
|
|
14
|
+
name: 'token1',
|
|
15
|
+
inputs: [],
|
|
16
|
+
outputs: [{ type: 'address' }],
|
|
17
|
+
stateMutability: 'view',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'function',
|
|
21
|
+
name: 'fee',
|
|
22
|
+
inputs: [],
|
|
23
|
+
outputs: [{ type: 'uint24' }],
|
|
24
|
+
stateMutability: 'view',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: 'function',
|
|
28
|
+
name: 'tickSpacing',
|
|
29
|
+
inputs: [],
|
|
30
|
+
outputs: [{ type: 'int24' }],
|
|
31
|
+
stateMutability: 'view',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: 'function',
|
|
35
|
+
name: 'liquidity',
|
|
36
|
+
inputs: [],
|
|
37
|
+
outputs: [{ type: 'uint128' }],
|
|
38
|
+
stateMutability: 'view',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'function',
|
|
42
|
+
name: 'slot0',
|
|
43
|
+
inputs: [],
|
|
44
|
+
outputs: [
|
|
45
|
+
{ name: 'sqrtPriceX96', type: 'uint160' },
|
|
46
|
+
{ name: 'tick', type: 'int24' },
|
|
47
|
+
{ name: 'observationIndex', type: 'uint16' },
|
|
48
|
+
{ name: 'observationCardinality', type: 'uint16' },
|
|
49
|
+
{ name: 'observationCardinalityNext', type: 'uint16' },
|
|
50
|
+
{ name: 'feeProtocol', type: 'uint8' },
|
|
51
|
+
{ name: 'unlocked', type: 'bool' },
|
|
52
|
+
],
|
|
53
|
+
stateMutability: 'view',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
type: 'function',
|
|
57
|
+
name: 'positions',
|
|
58
|
+
inputs: [{ name: 'key', type: 'bytes32' }],
|
|
59
|
+
outputs: [
|
|
60
|
+
{ name: 'liquidity', type: 'uint128' },
|
|
61
|
+
{ name: 'feeGrowthInside0LastX128', type: 'uint256' },
|
|
62
|
+
{ name: 'feeGrowthInside1LastX128', type: 'uint256' },
|
|
63
|
+
{ name: 'tokensOwed0', type: 'uint128' },
|
|
64
|
+
{ name: 'tokensOwed1', type: 'uint128' },
|
|
65
|
+
],
|
|
66
|
+
stateMutability: 'view',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: 'event',
|
|
70
|
+
name: 'Swap',
|
|
71
|
+
inputs: [
|
|
72
|
+
{ name: 'sender', type: 'address', indexed: true },
|
|
73
|
+
{ name: 'recipient', type: 'address', indexed: true },
|
|
74
|
+
{ name: 'amount0', type: 'int256', indexed: false },
|
|
75
|
+
{ name: 'amount1', type: 'int256', indexed: false },
|
|
76
|
+
{ name: 'sqrtPriceX96', type: 'uint160', indexed: false },
|
|
77
|
+
{ name: 'liquidity', type: 'uint128', indexed: false },
|
|
78
|
+
{ name: 'tick', type: 'int24', indexed: false },
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
] as const
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract Addresses for Lux Exchange
|
|
3
|
+
*/
|
|
4
|
+
import type { Address } from 'viem'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Contract addresses for Lux Mainnet (96369)
|
|
8
|
+
*/
|
|
9
|
+
export const LUX_MAINNET_CONTRACTS = {
|
|
10
|
+
// Core
|
|
11
|
+
WLUX: '0x55750d6CA62a041c06a8E28626b10Be6c688f471' as Address,
|
|
12
|
+
MULTICALL: '0xd25F88CBdAe3c2CCA3Bb75FC4E723b44C0Ea362F' as Address,
|
|
13
|
+
|
|
14
|
+
// Bridge tokens
|
|
15
|
+
LETH: '0xAA3AE95816a4A6FbC6b8Ed5a6C06f22A96A80C8C' as Address,
|
|
16
|
+
LBTC: '0x526903E35E7106D62ED3B5d77E14e51d024Aa1D3' as Address,
|
|
17
|
+
LUSD: '0x4B1BfA76eD63F1A0aD2E4f40b3F46C45E8F7A4E2' as Address,
|
|
18
|
+
|
|
19
|
+
// AMM V2 (QuantumSwap)
|
|
20
|
+
V2_FACTORY: '0xd9a95609DbB228A13568Bd9f9A285105E7596970' as Address,
|
|
21
|
+
V2_ROUTER: '0x1F6cbC7d3bc7D803ee76D80F0eEE25767431e674' as Address,
|
|
22
|
+
|
|
23
|
+
// AMM V3 (Concentrated Liquidity)
|
|
24
|
+
V3_FACTORY: '0xb732BD88F25EdD9C3456638671fB37685D4B4e3f' as Address,
|
|
25
|
+
V3_SWAP_ROUTER: '0xE8fb25086C8652c92f5AF90D730Bac7C63Fc9A58' as Address,
|
|
26
|
+
V3_SWAP_ROUTER_02: '0x939bC0Bca6F9B9c52E6e3AD8A3C590b5d9B9D10E' as Address,
|
|
27
|
+
V3_QUOTER: '0x12e2B76FaF4dDA5a173a4532916bb6Bfa3645275' as Address,
|
|
28
|
+
V3_QUOTER_V2: '0x15C729fdd833Ba675edd466Dfc63E1B737925A4c' as Address,
|
|
29
|
+
V3_TICK_LENS: '0x57A22965AdA0e52D785A9Aa155beF423D573b879' as Address,
|
|
30
|
+
V3_NFT_POSITION_MANAGER: '0x7a4C48B9dae0b7c396569b34042fcA604150Ee28' as Address,
|
|
31
|
+
V3_NFT_DESCRIPTOR: '0x53B1aAA5b6DDFD4eD00D0A7b5Ef333dc74B605b5' as Address,
|
|
32
|
+
} as const
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Contract addresses for Lux Testnet (96368)
|
|
36
|
+
*/
|
|
37
|
+
export const LUX_TESTNET_CONTRACTS = {
|
|
38
|
+
// Core
|
|
39
|
+
WLUX: '0x732740c5c895C9FCF619930ed4293fc858eb44c7' as Address,
|
|
40
|
+
WETH: '0xd9956542B51032d940ef076d70B69410667277A3' as Address,
|
|
41
|
+
MULTICALL: '0xd25F88CBdAe3c2CCA3Bb75FC4E723b44C0Ea362F' as Address,
|
|
42
|
+
|
|
43
|
+
// AMM V2
|
|
44
|
+
V2_FACTORY: '0x81C3669B139D92909AA67DbF74a241b10540d919' as Address,
|
|
45
|
+
V2_ROUTER: '0xDB6c703c80BFaE5F9a56482d3c8535f27E1136EB' as Address,
|
|
46
|
+
|
|
47
|
+
// AMM V3
|
|
48
|
+
V3_FACTORY: '0x80bBc7C4C7a59C899D1B37BC14539A22D5830a84' as Address,
|
|
49
|
+
V3_SWAP_ROUTER: '0xE8fb25086C8652c92f5AF90D730Bac7C63Fc9A58' as Address,
|
|
50
|
+
V3_SWAP_ROUTER_02: '0x939bC0Bca6F9B9c52E6e3AD8A3C590b5d9B9D10E' as Address,
|
|
51
|
+
V3_QUOTER: '0x12e2B76FaF4dDA5a173a4532916bb6Bfa3645275' as Address,
|
|
52
|
+
V3_QUOTER_V2: '0x15C729fdd833Ba675edd466Dfc63E1B737925A4c' as Address,
|
|
53
|
+
V3_TICK_LENS: '0x57A22965AdA0e52D785A9Aa155beF423D573b879' as Address,
|
|
54
|
+
V3_NFT_POSITION_MANAGER: '0x7a4C48B9dae0b7c396569b34042fcA604150Ee28' as Address,
|
|
55
|
+
V3_NFT_DESCRIPTOR: '0x53B1aAA5b6DDFD4eD00D0A7b5Ef333dc74B605b5' as Address,
|
|
56
|
+
} as const
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* DEX Precompile addresses (native AMM)
|
|
60
|
+
* These provide sub-microsecond execution
|
|
61
|
+
*
|
|
62
|
+
* Lux Precompile Address Standard:
|
|
63
|
+
* - Prefix format: 0xNNNN000000000000000000000000000000000000
|
|
64
|
+
* - Range 0x0400-0x04FF is reserved for DEX precompiles
|
|
65
|
+
*
|
|
66
|
+
* @see ~/work/lux/precompile/dex/module.go for implementation
|
|
67
|
+
*/
|
|
68
|
+
export const DEX_PRECOMPILES = {
|
|
69
|
+
POOL_MANAGER: '0x0400000000000000000000000000000000000000' as Address,
|
|
70
|
+
SWAP_ROUTER: '0x0401000000000000000000000000000000000000' as Address,
|
|
71
|
+
HOOKS_REGISTRY: '0x0402000000000000000000000000000000000000' as Address,
|
|
72
|
+
FLASH_LOAN: '0x0403000000000000000000000000000000000000' as Address,
|
|
73
|
+
LENDING: '0x0410000000000000000000000000000000000000' as Address,
|
|
74
|
+
LIQUID: '0x0430000000000000000000000000000000000000' as Address,
|
|
75
|
+
TELEPORT: '0x0440000000000000000000000000000000000000' as Address,
|
|
76
|
+
} as const
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Contract addresses for Lux Dev (1337)
|
|
80
|
+
*/
|
|
81
|
+
export const LUX_DEV_CONTRACTS = {
|
|
82
|
+
// Core
|
|
83
|
+
WLUX: '0x610178dA211FEF7D417bC0e6FeD39F05609AD788' as Address,
|
|
84
|
+
MULTICALL: '0xd25F88CBdAe3c2CCA3Bb75FC4E723b44C0Ea362F' as Address,
|
|
85
|
+
|
|
86
|
+
// Bridged tokens (local dev)
|
|
87
|
+
ETH: '0x5FbDB2315678afecb367f032d93F642f64180aa3' as Address,
|
|
88
|
+
BTC: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512' as Address,
|
|
89
|
+
USDC: '0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0' as Address,
|
|
90
|
+
USDT: '0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9' as Address,
|
|
91
|
+
DAI: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9' as Address,
|
|
92
|
+
AI: '0x0B306BF915C4d645ff596e518fAf3F9669b97016' as Address,
|
|
93
|
+
|
|
94
|
+
// AMM V2
|
|
95
|
+
V2_FACTORY: '0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1' as Address,
|
|
96
|
+
V2_ROUTER: '0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE' as Address,
|
|
97
|
+
|
|
98
|
+
// AMM V3 (uses testnet addresses for dev)
|
|
99
|
+
V3_FACTORY: '0x80bBc7C4C7a59C899D1B37BC14539A22D5830a84' as Address,
|
|
100
|
+
V3_SWAP_ROUTER: '0xE8fb25086C8652c92f5AF90D730Bac7C63Fc9A58' as Address,
|
|
101
|
+
V3_SWAP_ROUTER_02: '0x939bC0Bca6F9B9c52E6e3AD8A3C590b5d9B9D10E' as Address,
|
|
102
|
+
V3_QUOTER: '0x12e2B76FaF4dDA5a173a4532916bb6Bfa3645275' as Address,
|
|
103
|
+
V3_QUOTER_V2: '0x15C729fdd833Ba675edd466Dfc63E1B737925A4c' as Address,
|
|
104
|
+
V3_TICK_LENS: '0x57A22965AdA0e52D785A9Aa155beF423D573b879' as Address,
|
|
105
|
+
V3_NFT_POSITION_MANAGER: '0x7a4C48B9dae0b7c396569b34042fcA604150Ee28' as Address,
|
|
106
|
+
V3_NFT_DESCRIPTOR: '0x53B1aAA5b6DDFD4eD00D0A7b5Ef333dc74B605b5' as Address,
|
|
107
|
+
|
|
108
|
+
// Staking
|
|
109
|
+
STAKED_LUX: '0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0' as Address,
|
|
110
|
+
} as const
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get contracts for a specific chain
|
|
114
|
+
*/
|
|
115
|
+
export function getContracts(chainId: number) {
|
|
116
|
+
switch (chainId) {
|
|
117
|
+
case 96369:
|
|
118
|
+
return LUX_MAINNET_CONTRACTS
|
|
119
|
+
case 96368:
|
|
120
|
+
return LUX_TESTNET_CONTRACTS
|
|
121
|
+
case 1337:
|
|
122
|
+
return LUX_DEV_CONTRACTS
|
|
123
|
+
default:
|
|
124
|
+
return LUX_TESTNET_CONTRACTS
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type ContractAddresses = typeof LUX_MAINNET_CONTRACTS
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { BalanceDelta } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create balance delta from packed int256 (Solidity representation)
|
|
5
|
+
* Upper 128 bits = amount0, Lower 128 bits = amount1
|
|
6
|
+
*/
|
|
7
|
+
export function unpackBalanceDelta(packed: bigint): BalanceDelta {
|
|
8
|
+
const amount0 = packed >> 128n
|
|
9
|
+
const amount1 = BigInt.asIntN(128, packed)
|
|
10
|
+
return { amount0, amount1 }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Pack balance delta into int256
|
|
15
|
+
*/
|
|
16
|
+
export function packBalanceDelta(delta: BalanceDelta): bigint {
|
|
17
|
+
return (delta.amount0 << 128n) | (delta.amount1 & ((1n << 128n) - 1n))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Add two balance deltas
|
|
22
|
+
*/
|
|
23
|
+
export function addBalanceDeltas(a: BalanceDelta, b: BalanceDelta): BalanceDelta {
|
|
24
|
+
return {
|
|
25
|
+
amount0: a.amount0 + b.amount0,
|
|
26
|
+
amount1: a.amount1 + b.amount1,
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Negate balance delta
|
|
32
|
+
*/
|
|
33
|
+
export function negateBalanceDelta(delta: BalanceDelta): BalanceDelta {
|
|
34
|
+
return {
|
|
35
|
+
amount0: -delta.amount0,
|
|
36
|
+
amount1: -delta.amount1,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if balance delta is zero
|
|
42
|
+
*/
|
|
43
|
+
export function isZeroDelta(delta: BalanceDelta): boolean {
|
|
44
|
+
return delta.amount0 === 0n && delta.amount1 === 0n
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the amount for a specific currency (0 or 1)
|
|
49
|
+
*/
|
|
50
|
+
export function getDeltaAmount(delta: BalanceDelta, currency: 0 | 1): bigint {
|
|
51
|
+
return currency === 0 ? delta.amount0 : delta.amount1
|
|
52
|
+
}
|
package/src/dex/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { keccak256, encodeAbiParameters, type Address } from 'viem'
|
|
2
|
+
import type { PoolKey, Currency } from './types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sort currencies to ensure currency0 < currency1
|
|
6
|
+
*/
|
|
7
|
+
export function sortCurrencies(currencyA: Currency, currencyB: Currency): [Currency, Currency] {
|
|
8
|
+
const a = BigInt(currencyA)
|
|
9
|
+
const b = BigInt(currencyB)
|
|
10
|
+
return a < b ? [currencyA, currencyB] : [currencyB, currencyA]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create a pool key from parameters
|
|
15
|
+
*/
|
|
16
|
+
export function createPoolKey(
|
|
17
|
+
currencyA: Currency,
|
|
18
|
+
currencyB: Currency,
|
|
19
|
+
fee: number,
|
|
20
|
+
tickSpacing: number,
|
|
21
|
+
hooks: Address = '0x0000000000000000000000000000000000000000'
|
|
22
|
+
): PoolKey {
|
|
23
|
+
const [currency0, currency1] = sortCurrencies(currencyA, currencyB)
|
|
24
|
+
return {
|
|
25
|
+
currency0,
|
|
26
|
+
currency1,
|
|
27
|
+
fee,
|
|
28
|
+
tickSpacing,
|
|
29
|
+
hooks,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Compute pool ID from pool key
|
|
35
|
+
*/
|
|
36
|
+
export function computePoolId(key: PoolKey): `0x${string}` {
|
|
37
|
+
return keccak256(
|
|
38
|
+
encodeAbiParameters(
|
|
39
|
+
[
|
|
40
|
+
{ type: 'address', name: 'currency0' },
|
|
41
|
+
{ type: 'address', name: 'currency1' },
|
|
42
|
+
{ type: 'uint24', name: 'fee' },
|
|
43
|
+
{ type: 'int24', name: 'tickSpacing' },
|
|
44
|
+
{ type: 'address', name: 'hooks' },
|
|
45
|
+
],
|
|
46
|
+
[key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks]
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Check if two pool keys are equal
|
|
53
|
+
*/
|
|
54
|
+
export function poolKeysEqual(a: PoolKey, b: PoolKey): boolean {
|
|
55
|
+
return (
|
|
56
|
+
a.currency0.toLowerCase() === b.currency0.toLowerCase() &&
|
|
57
|
+
a.currency1.toLowerCase() === b.currency1.toLowerCase() &&
|
|
58
|
+
a.fee === b.fee &&
|
|
59
|
+
a.tickSpacing === b.tickSpacing &&
|
|
60
|
+
a.hooks.toLowerCase() === b.hooks.toLowerCase()
|
|
61
|
+
)
|
|
62
|
+
}
|
package/src/dex/types.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Address } from 'viem'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Currency type - address(0) represents native token
|
|
5
|
+
*/
|
|
6
|
+
export type Currency = Address
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Pool key uniquely identifies a pool
|
|
10
|
+
*/
|
|
11
|
+
export interface PoolKey {
|
|
12
|
+
currency0: Currency
|
|
13
|
+
currency1: Currency
|
|
14
|
+
fee: number // uint24 - fee in hundredths of a bip (e.g., 3000 = 0.30%)
|
|
15
|
+
tickSpacing: number // int24
|
|
16
|
+
hooks: Address // Hook contract address (address(0) = no hooks)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Balance delta represents changes in token balances
|
|
21
|
+
* Positive = user owes pool, Negative = pool owes user
|
|
22
|
+
*/
|
|
23
|
+
export interface BalanceDelta {
|
|
24
|
+
amount0: bigint
|
|
25
|
+
amount1: bigint
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Swap parameters
|
|
30
|
+
*/
|
|
31
|
+
export interface SwapParams {
|
|
32
|
+
zeroForOne: boolean // Direction: true = token0 -> token1
|
|
33
|
+
amountSpecified: bigint // Positive = exact input, Negative = exact output
|
|
34
|
+
sqrtPriceLimitX96: bigint // Price limit (0 for no limit)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Modify liquidity parameters
|
|
39
|
+
*/
|
|
40
|
+
export interface ModifyLiquidityParams {
|
|
41
|
+
tickLower: number
|
|
42
|
+
tickUpper: number
|
|
43
|
+
liquidityDelta: bigint
|
|
44
|
+
salt: `0x${string}`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Pool slot0 state
|
|
49
|
+
*/
|
|
50
|
+
export interface Slot0 {
|
|
51
|
+
sqrtPriceX96: bigint
|
|
52
|
+
tick: number
|
|
53
|
+
protocolFee: number
|
|
54
|
+
lpFee: number
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Fee tiers (in hundredths of a bip)
|
|
59
|
+
*/
|
|
60
|
+
export const FEE_TIERS = {
|
|
61
|
+
LOWEST: 100, // 0.01%
|
|
62
|
+
LOW: 500, // 0.05%
|
|
63
|
+
MEDIUM: 3000, // 0.30%
|
|
64
|
+
HIGH: 10000, // 1.00%
|
|
65
|
+
} as const
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Tick spacing for fee tiers
|
|
69
|
+
*/
|
|
70
|
+
export const TICK_SPACINGS: Record<number, number> = {
|
|
71
|
+
100: 1,
|
|
72
|
+
500: 10,
|
|
73
|
+
3000: 60,
|
|
74
|
+
10000: 200,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Native currency constant
|
|
79
|
+
*/
|
|
80
|
+
export const NATIVE_CURRENCY: Currency = '0x0000000000000000000000000000000000000000'
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if currency is native
|
|
84
|
+
*/
|
|
85
|
+
export function isNativeCurrency(currency: Currency): boolean {
|
|
86
|
+
return currency === NATIVE_CURRENCY
|
|
87
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useQuery } from '@tanstack/react-query'
|
|
4
|
+
import { usePublicClient } from 'wagmi'
|
|
5
|
+
import { getContracts } from '../contracts'
|
|
6
|
+
import { UNISWAP_V3_FACTORY_ABI, UNISWAP_V3_POOL_ABI } from '../contracts/abis'
|
|
7
|
+
import type { Address } from 'viem'
|
|
8
|
+
|
|
9
|
+
export interface Pool {
|
|
10
|
+
address: Address
|
|
11
|
+
token0: Address
|
|
12
|
+
token1: Address
|
|
13
|
+
fee: number
|
|
14
|
+
tickSpacing: number
|
|
15
|
+
liquidity: bigint
|
|
16
|
+
sqrtPriceX96: bigint
|
|
17
|
+
tick: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Hook to get pool information
|
|
22
|
+
*/
|
|
23
|
+
export function usePool(
|
|
24
|
+
token0: Address | undefined,
|
|
25
|
+
token1: Address | undefined,
|
|
26
|
+
fee: number,
|
|
27
|
+
chainId: number
|
|
28
|
+
) {
|
|
29
|
+
const publicClient = usePublicClient({ chainId })
|
|
30
|
+
const contracts = getContracts(chainId)
|
|
31
|
+
|
|
32
|
+
return useQuery({
|
|
33
|
+
queryKey: ['pool', token0, token1, fee, chainId],
|
|
34
|
+
queryFn: async (): Promise<Pool | null> => {
|
|
35
|
+
if (!token0 || !token1 || !publicClient) return null
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// Get pool address from factory
|
|
39
|
+
const poolAddress = await publicClient.readContract({
|
|
40
|
+
address: contracts.V3_FACTORY,
|
|
41
|
+
abi: UNISWAP_V3_FACTORY_ABI,
|
|
42
|
+
functionName: 'getPool',
|
|
43
|
+
args: [token0, token1, fee],
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (poolAddress === '0x0000000000000000000000000000000000000000') {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Get pool state
|
|
51
|
+
const [slot0, liquidity, tickSpacing] = await Promise.all([
|
|
52
|
+
publicClient.readContract({
|
|
53
|
+
address: poolAddress,
|
|
54
|
+
abi: UNISWAP_V3_POOL_ABI,
|
|
55
|
+
functionName: 'slot0',
|
|
56
|
+
}),
|
|
57
|
+
publicClient.readContract({
|
|
58
|
+
address: poolAddress,
|
|
59
|
+
abi: UNISWAP_V3_POOL_ABI,
|
|
60
|
+
functionName: 'liquidity',
|
|
61
|
+
}),
|
|
62
|
+
publicClient.readContract({
|
|
63
|
+
address: poolAddress,
|
|
64
|
+
abi: UNISWAP_V3_POOL_ABI,
|
|
65
|
+
functionName: 'tickSpacing',
|
|
66
|
+
}),
|
|
67
|
+
])
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
address: poolAddress,
|
|
71
|
+
token0,
|
|
72
|
+
token1,
|
|
73
|
+
fee,
|
|
74
|
+
tickSpacing,
|
|
75
|
+
liquidity,
|
|
76
|
+
sqrtPriceX96: slot0[0],
|
|
77
|
+
tick: slot0[1],
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('Failed to fetch pool:', error)
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
enabled: !!token0 && !!token1 && !!publicClient,
|
|
85
|
+
staleTime: 30_000,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Hook to get all pools for a token pair
|
|
91
|
+
*/
|
|
92
|
+
export function usePools(
|
|
93
|
+
token0: Address | undefined,
|
|
94
|
+
token1: Address | undefined,
|
|
95
|
+
chainId: number
|
|
96
|
+
) {
|
|
97
|
+
const pool100 = usePool(token0, token1, 100, chainId)
|
|
98
|
+
const pool500 = usePool(token0, token1, 500, chainId)
|
|
99
|
+
const pool3000 = usePool(token0, token1, 3000, chainId)
|
|
100
|
+
const pool10000 = usePool(token0, token1, 10000, chainId)
|
|
101
|
+
|
|
102
|
+
const pools = [
|
|
103
|
+
pool100.data,
|
|
104
|
+
pool500.data,
|
|
105
|
+
pool3000.data,
|
|
106
|
+
pool10000.data,
|
|
107
|
+
].filter((p): p is Pool => p !== null)
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
pools,
|
|
111
|
+
isLoading: pool100.isLoading || pool500.isLoading || pool3000.isLoading || pool10000.isLoading,
|
|
112
|
+
bestPool: pools.length > 0 ? pools.reduce((best, pool) =>
|
|
113
|
+
pool.liquidity > best.liquidity ? pool : best
|
|
114
|
+
) : null,
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useQuery } from '@tanstack/react-query'
|
|
4
|
+
import { usePublicClient } from 'wagmi'
|
|
5
|
+
import { getContracts } from '../contracts'
|
|
6
|
+
import { NFT_POSITION_MANAGER_ABI } from '../contracts/abis'
|
|
7
|
+
import type { Address } from 'viem'
|
|
8
|
+
|
|
9
|
+
export interface Position {
|
|
10
|
+
tokenId: bigint
|
|
11
|
+
token0: Address
|
|
12
|
+
token1: Address
|
|
13
|
+
fee: number
|
|
14
|
+
tickLower: number
|
|
15
|
+
tickUpper: number
|
|
16
|
+
liquidity: bigint
|
|
17
|
+
tokensOwed0: bigint
|
|
18
|
+
tokensOwed1: bigint
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook to get user's liquidity positions
|
|
23
|
+
*/
|
|
24
|
+
export function usePositions(owner: Address | undefined, chainId: number) {
|
|
25
|
+
const publicClient = usePublicClient({ chainId })
|
|
26
|
+
const contracts = getContracts(chainId)
|
|
27
|
+
|
|
28
|
+
return useQuery({
|
|
29
|
+
queryKey: ['positions', owner, chainId],
|
|
30
|
+
queryFn: async (): Promise<Position[]> => {
|
|
31
|
+
if (!owner || !publicClient) return []
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Get number of positions
|
|
35
|
+
const balance = await publicClient.readContract({
|
|
36
|
+
address: contracts.V3_NFT_POSITION_MANAGER,
|
|
37
|
+
abi: NFT_POSITION_MANAGER_ABI,
|
|
38
|
+
functionName: 'balanceOf',
|
|
39
|
+
args: [owner],
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (balance === 0n) return []
|
|
43
|
+
|
|
44
|
+
// Get all token IDs
|
|
45
|
+
const tokenIds = await Promise.all(
|
|
46
|
+
Array.from({ length: Number(balance) }, (_, i) =>
|
|
47
|
+
publicClient.readContract({
|
|
48
|
+
address: contracts.V3_NFT_POSITION_MANAGER,
|
|
49
|
+
abi: NFT_POSITION_MANAGER_ABI,
|
|
50
|
+
functionName: 'tokenOfOwnerByIndex',
|
|
51
|
+
args: [owner, BigInt(i)],
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
// Get position details for each token ID
|
|
57
|
+
const positions = await Promise.all(
|
|
58
|
+
tokenIds.map(async (tokenId) => {
|
|
59
|
+
const position = await publicClient.readContract({
|
|
60
|
+
address: contracts.V3_NFT_POSITION_MANAGER,
|
|
61
|
+
abi: NFT_POSITION_MANAGER_ABI,
|
|
62
|
+
functionName: 'positions',
|
|
63
|
+
args: [tokenId],
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
tokenId,
|
|
68
|
+
token0: position[2],
|
|
69
|
+
token1: position[3],
|
|
70
|
+
fee: position[4],
|
|
71
|
+
tickLower: position[5],
|
|
72
|
+
tickUpper: position[6],
|
|
73
|
+
liquidity: position[7],
|
|
74
|
+
tokensOwed0: position[10],
|
|
75
|
+
tokensOwed1: position[11],
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
// Filter out closed positions (zero liquidity)
|
|
81
|
+
return positions.filter((p) => p.liquidity > 0n)
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error('Failed to fetch positions:', error)
|
|
84
|
+
return []
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
enabled: !!owner && !!publicClient,
|
|
88
|
+
staleTime: 60_000,
|
|
89
|
+
})
|
|
90
|
+
}
|