@w3lib/evm-batch-call 0.5.0 → 0.6.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/CHANGELOG.md +14 -0
- package/README.md +79 -2
- package/dist/liquidity/common.d.ts +72 -0
- package/dist/liquidity/common.d.ts.map +1 -0
- package/dist/liquidity/common.js +271 -0
- package/dist/liquidity/common.js.map +1 -0
- package/dist/liquidity/concentrated.d.ts +19 -0
- package/dist/liquidity/concentrated.d.ts.map +1 -0
- package/dist/liquidity/concentrated.js +106 -0
- package/dist/liquidity/concentrated.js.map +1 -0
- package/dist/liquidity/index.d.ts +42 -0
- package/dist/liquidity/index.d.ts.map +1 -0
- package/dist/liquidity/index.js +143 -0
- package/dist/liquidity/index.js.map +1 -0
- package/dist/liquidity/types.d.ts +182 -0
- package/dist/liquidity/types.d.ts.map +1 -0
- package/dist/liquidity/types.js +2 -0
- package/dist/liquidity/types.js.map +1 -0
- package/dist/liquidity/v2.d.ts +5 -0
- package/dist/liquidity/v2.d.ts.map +1 -0
- package/dist/liquidity/v2.js +342 -0
- package/dist/liquidity/v2.js.map +1 -0
- package/dist/liquidity/v3.d.ts +6 -0
- package/dist/liquidity/v3.d.ts.map +1 -0
- package/dist/liquidity/v3.js +310 -0
- package/dist/liquidity/v3.js.map +1 -0
- package/dist/liquidity/v4.d.ts +5 -0
- package/dist/liquidity/v4.d.ts.map +1 -0
- package/dist/liquidity/v4.js +279 -0
- package/dist/liquidity/v4.js.map +1 -0
- package/dist/lp.d.ts +8 -1
- package/dist/lp.d.ts.map +1 -1
- package/dist/lp.js +29 -18
- package/dist/lp.js.map +1 -1
- package/dist/lpMath.d.ts +55 -0
- package/dist/lpMath.d.ts.map +1 -1
- package/dist/lpMath.js +209 -0
- package/dist/lpMath.js.map +1 -1
- package/dist/subpaths/liquidity.d.ts +24 -0
- package/dist/subpaths/liquidity.d.ts.map +1 -0
- package/dist/subpaths/liquidity.js +21 -0
- package/dist/subpaths/liquidity.js.map +1 -0
- package/dist/subpaths/lp.d.ts +1 -1
- package/dist/subpaths/lp.d.ts.map +1 -1
- package/dist/subpaths/lp.js +1 -1
- package/dist/subpaths/lp.js.map +1 -1
- package/dist/write/tron.d.ts +2 -0
- package/dist/write/tron.d.ts.map +1 -1
- package/dist/write/tron.js +4 -0
- package/dist/write/tron.js.map +1 -1
- package/package.json +20 -12
- package/src/liquidity/common.ts +314 -0
- package/src/liquidity/concentrated.ts +121 -0
- package/src/liquidity/index.ts +171 -0
- package/src/liquidity/types.ts +194 -0
- package/src/liquidity/v2.ts +371 -0
- package/src/liquidity/v3.ts +382 -0
- package/src/liquidity/v4.ts +348 -0
- package/src/lp.ts +36 -18
- package/src/lpMath.ts +223 -0
- package/src/subpaths/liquidity.ts +52 -0
- package/src/subpaths/lp.ts +20 -1
- package/src/write/tron.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### 新功能
|
|
6
|
+
|
|
7
|
+
- 添加 / 移除流动性,子路径 `@w3lib/evm-batch-call/liquidity`:
|
|
8
|
+
- `buildAddLiquidity` / `buildRemoveLiquidity` / `buildCollectFees` 只构建(报价 + 按顺序发送的交易,授权在前),`addLiquidity` / `removeLiquidity` / `collectFees` 构建后签名发送(钱包同 `/write`)
|
|
9
|
+
- V2:Router 的 `addLiquidity(ETH)` / `removeLiquidity(ETH)`,数量与 Router 的取整逐位一致;V3:`mint` / `increaseLiquidity` / `decreaseLiquidity` + `collect`(+ `burn`),池子不存在时可传 `initialPrice` 创建;V4:PositionManager 的 actions + Permit2 授权,主币池子
|
|
10
|
+
- 新建仓位按价格区间(tokenB / tokenA)、tick 或全区间,给一边的数量自动算另一边;往已有仓位追加、按比例移除可以直接传 `getLpPositions` 的结果
|
|
11
|
+
- 主币:V2 / V3 的包装币那一边可以用主币支付 / 收取;滑点按价格范围算 V3 的 `amountMin`、V4 的 `amountMax` 和移除的最小数量
|
|
12
|
+
- Tron 的 SunSwap V2 / V3 同样支持
|
|
13
|
+
- `LpProtocol.router`:V2 协议的 Router(内置表里的 V2 协议都已填好、在链上核对过)。SunSwap V2 用 SunSwap 网页当前使用的 Router
|
|
14
|
+
- `LpProtocol.protocolFee`:V2 协议手续费给 feeTo 增发的比例(`'1/6'` / `'8/25'`),添加 / 移除时按它算 LP 总量
|
|
15
|
+
- `/lp` 的数学工具新增 `getLiquidityForAmounts`、`getMintAmounts`、`getTickAtSqrtRatio`、`priceToTick`、`priceToSqrtPriceX96`、`nearestUsableTick` 等(也从 `/liquidity` 导出)
|
|
16
|
+
|
|
3
17
|
## 0.5.0
|
|
4
18
|
|
|
5
19
|
### 新功能
|
package/README.md
CHANGED
|
@@ -53,8 +53,9 @@ await getErc1155Balances(user, [{ contract: ITEMS, tokenId: 7 }], { chainId: 137
|
|
|
53
53
|
| `getErc1155Balances(owner, items, opts)` | `erc1155Balances(multi, owner, items)` | **`/nft`**。ERC1155 余额 |
|
|
54
54
|
| `getOwnerTokens(owner, opts)` | `ownerTokens(multi, owner, opts)` | **子路径 `/owner`**。资产列表:地址持有的代币(**不推荐使用**,结果不保证完整,见[资产列表](#资产列表)) |
|
|
55
55
|
| `getLpPositions(owner, opts)` | `lpPositions(multi, owner, opts)` | **子路径 `/lp`**。LP 仓位:V2 的 LP 代币、V3 / V4 的仓位 NFT,代币数量、未领取手续费、可选美元价值,见 [LP 仓位](#lp-仓位) |
|
|
56
|
+
| | `addLiquidity` / `removeLiquidity` / `collectFees`(`build*` 只构建不发送) | **子路径 `/liquidity`**。添加 / 移除流动性、领取手续费,见[添加 / 移除流动性](#添加--移除流动性) |
|
|
56
57
|
|
|
57
|
-
**子路径**:NFT 查询在 `@w3lib/evm-batch-call/nft`,资产列表(含代币来源、价格源、Transfer 增量扫描)在 `@w3lib/evm-batch-call/owner`,LP 仓位在 `@w3lib/evm-batch-call/lp`,批量写操作在 `@w3lib/evm-batch-call/write`。不用这些功能时打包不会带上它们的代码(拆出后约少 15KB:只用 `getBalances` 时 minify 后约 50KB、gzip 约 17KB,均不含 ethers)。
|
|
58
|
+
**子路径**:NFT 查询在 `@w3lib/evm-batch-call/nft`,资产列表(含代币来源、价格源、Transfer 增量扫描)在 `@w3lib/evm-batch-call/owner`,LP 仓位在 `@w3lib/evm-batch-call/lp`,添加 / 移除流动性在 `@w3lib/evm-batch-call/liquidity`,批量写操作在 `@w3lib/evm-batch-call/write`。不用这些功能时打包不会带上它们的代码(拆出后约少 15KB:只用 `getBalances` 时 minify 后约 50KB、gzip 约 17KB,均不含 ethers)。
|
|
58
59
|
|
|
59
60
|
共同的规则:
|
|
60
61
|
|
|
@@ -275,7 +276,7 @@ await getLpPositions(user, { chainId: 1, v4: { scan: { storage } } }) //
|
|
|
275
276
|
| Avalanche | | Uniswap | |
|
|
276
277
|
| Tron | SunSwap | SunSwap | |
|
|
277
278
|
|
|
278
|
-
地址都在链上核对过(2026-10)。其他 DEX / 链传自己的协议:`protocols: [{ id: 'my-dex', name: 'My DEX', version: 'v3', chainId, positionManager, factory }]`(V2 只需要 `factory`;V3 需要 `positionManager` 和 `factory`,ABI 与 Uniswap V3 相同的分叉都可以;V4 需要 `positionManager` 和 `stateView`,`deployBlock` 可选)。`protocols: ['uniswap-v3']` 只查某些协议,`versions: ['v3']` 只查某些类型。
|
|
279
|
+
地址都在链上核对过(2026-10)。其他 DEX / 链传自己的协议:`protocols: [{ id: 'my-dex', name: 'My DEX', version: 'v3', chainId, positionManager, factory }]`(V2 只需要 `factory`,添加 / 移除流动性还要 `router`;V3 需要 `positionManager` 和 `factory`,ABI 与 Uniswap V3 相同的分叉都可以;V4 需要 `positionManager` 和 `stateView`,`deployBlock` 可选)。`protocols: ['uniswap-v3']` 只查某些协议,`versions: ['v3']` 只查某些类型。
|
|
279
280
|
|
|
280
281
|
### 每种类型怎么查、能不能查全
|
|
281
282
|
|
|
@@ -298,6 +299,78 @@ await getLpPositions(user, { chainId: 1, v4: { scan: { storage } } }) //
|
|
|
298
299
|
|
|
299
300
|
**局限**:PancakeSwap 等质押到农场(MasterChef)的仓位 NFT 不在用户名下,查不到;V2 只能尽量查(见上表);V4 需要传 `tokenIds` 或开启扫描。
|
|
300
301
|
|
|
302
|
+
## 添加 / 移除流动性
|
|
303
|
+
|
|
304
|
+
子路径 `@w3lib/evm-batch-call/liquidity`:V2(通过 Router)、V3(仓位 NFT)、Uniswap V4(PositionManager + Permit2),协议与 [LP 仓位](#内置的协议) 的内置表相同(含 Tron 的 SunSwap V2 / V3)。
|
|
305
|
+
|
|
306
|
+
- `buildAddLiquidity` / `buildRemoveLiquidity` / `buildCollectFees`:只读取、不签名,返回预计的数量和要按顺序发送的交易(授权在前)。可以当作报价(输入一边的数量,看另一边要多少),也可以把 `transactions` 交给钱包自己发送
|
|
307
|
+
- `addLiquidity` / `removeLiquidity` / `collectFees`:构建后签名发送,钱包与 `/write` 的 `batchCall` 相同(私钥、ethers Signer、浏览器钱包;Tron 上还可以是 tronWeb / tronwallet-adapter)。授权不够时先发授权交易,等它确认后再发主交易;授权失败时不发主交易
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
import { NATIVE_TOKEN, Provider } from '@w3lib/evm-batch-call'
|
|
311
|
+
import { getLpPositions } from '@w3lib/evm-batch-call/lp'
|
|
312
|
+
import { addLiquidity, buildAddLiquidity, collectFees, removeLiquidity } from '@w3lib/evm-batch-call/liquidity'
|
|
313
|
+
|
|
314
|
+
const multi = new Provider(56, rpc)
|
|
315
|
+
|
|
316
|
+
// 报价:新建 V3 仓位,价格区间是“1 个 tokenA 值多少个 tokenB”,给一边的数量
|
|
317
|
+
const plan = await buildAddLiquidity(multi, owner, {
|
|
318
|
+
protocol: 'pancakeswap-v3', tokenA: WBNB, tokenB: USDT, fee: 500,
|
|
319
|
+
priceLower: 550, priceUpper: 650, // 或 fullRange: true,或 tickLower / tickUpper
|
|
320
|
+
amountAFormatted: '1', // 或 amountA(最小单位);也可以两边都给
|
|
321
|
+
})
|
|
322
|
+
// { version: 'v3', token0, token1, tickLower, tickUpper, tick, price, liquidity,
|
|
323
|
+
// amount0Formatted, amount1Formatted, // 按当前价格预计存入的数量
|
|
324
|
+
// amount0Max, amount1Max, native: null, value: '0',
|
|
325
|
+
// transactions: [{ kind: 'approve', to: USDT, data, value: '0', token, spender, amount }, …, { kind: 'add', to: positionManager, data, value }] }
|
|
326
|
+
|
|
327
|
+
// 发送:主币直接用 NATIVE_TOKEN(V2 / V3 换成包装币、附带主币支付;V4 是主币池子)
|
|
328
|
+
const { status, tokenId, results } = await addLiquidity(multi, privateKey, {
|
|
329
|
+
protocol: 'uniswap-v2', tokenA: NATIVE_TOKEN, tokenB: USDT, amountAFormatted: '0.5',
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
// 已有仓位:直接用 getLpPositions 的结果(或 { protocol, tokenId } / { pool })
|
|
333
|
+
const [position] = await getLpPositions(owner, { chainId: 56 })
|
|
334
|
+
await addLiquidity(multi, privateKey, { position, amount0Formatted: '0.1' }) // 追加,另一边按当前价格算
|
|
335
|
+
await removeLiquidity(multi, privateKey, { position, percent: 50 }) // 按比例移除(V3 / V4 同时领取全部手续费)
|
|
336
|
+
await removeLiquidity(multi, privateKey, { position, burn: true }, { native: true }) // 全部移除、销毁 NFT,包装币换成主币
|
|
337
|
+
await collectFees(multi, privateKey, { position }) // 只领取手续费
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
| | V2 | V3 | V4 |
|
|
341
|
+
| --- | --- | --- | --- |
|
|
342
|
+
| 新建 / 追加 | Router `addLiquidity(ETH)`,池子不存在时创建(两边数量都要给) | `mint` / `increaseLiquidity`;池子不存在时传 `initialPrice` 创建 | `MINT_POSITION` / `INCREASE_LIQUIDITY`;池子没初始化时传 `initialPrice` |
|
|
343
|
+
| 移除 | Router `removeLiquidity(ETH)`,先授权 LP 代币 | `decreaseLiquidity` + `collect`(+ `burn`),用 multicall 合成一笔 | `DECREASE_LIQUIDITY` / `BURN_POSITION` + `TAKE_PAIR` |
|
|
344
|
+
| 授权 | 代币授权给 Router | 代币授权给仓位合约 | 代币授权给 Permit2,再在 Permit2 里授权给仓位合约(30 天有效) |
|
|
345
|
+
| 主币 | `native: true` 或 `tokenA` 传主币:包装币那一边用主币 | 同 V2(`refundETH` / `unwrapWETH9` + `sweepToken`) | 主币池子(`currency0` 是零地址)直接用主币 |
|
|
346
|
+
| 手续费 | 已计入 LP 份额 | 追加不领取;移除时一并领取,`collectFees` 单独领取 | 修改流动性时自动领取(计划里的 `fees0` / `fees1`) |
|
|
347
|
+
|
|
348
|
+
选项(构建和发送都可以传):
|
|
349
|
+
|
|
350
|
+
- `slippage`:价格滑点,默认 `0.005`(0.5%)。V2 是数量 × (1 − 滑点);V3 / V4 按价格在 `[p × (1 − s), p × (1 + s)]` 内变动时的数量算:V3 添加给出 `amountMin`(三个价格下合约实际会用掉的最小值),V4 添加给出 `amountMax`(会多授权 / 附带一点,用不完的不扣、主币退回),移除给出 `amount0Min` / `amount1Min`
|
|
351
|
+
- `deadline`:交易有效期(秒),默认 1200;`recipient`:收到 LP 代币 / NFT / 移除的代币的地址,默认发送者
|
|
352
|
+
- `approve`:`'exact'`(默认,本次需要的数量)或 `'max'`。已有非零但不够的额度直接改成新额度;只有 Ethereum 上的 USDT 等要求先归零的代币才先 approve 0(有的代币反过来不允许 approve 0)
|
|
353
|
+
- `native`:V2 / V3 的包装币那一边用主币支付 / 收取(新建时 `tokenA` / `tokenB` 传主币地址会自动开启)
|
|
354
|
+
- `protocols`:内置表里没有的协议(自己的 `LpProtocol`,V2 要带 `router`);`hookData`:V4 传给 hooks 的数据
|
|
355
|
+
- 发送时还有 `/write` 的发送参数(`wait`、`timeout`、`gasPrice`、`signal`、`onUpdate`…)和 `checkBalance`(默认 true:代币按预计数量、主币按 `value` 检查余额,不够时直接报错,不发交易)
|
|
356
|
+
|
|
357
|
+
数值:
|
|
358
|
+
|
|
359
|
+
- **流动性**:V3 / V4 的 `liquidity` 与合约算出来的逐位一致;V2 的 LP 数量和移除数量已按协议手续费算过(`feeTo` 开启时每次添加 / 移除前先给手续费地址增发 LP:比例看 `LpProtocol.protocolFee`:内置的 Uniswap / SushiSwap / SunSwap 是 `'1/6'`,PancakeSwap 是 `'8/25'`;自定义协议没填时按 `'8/25'` 偏保守地算),Uniswap V2 和 SunSwap V2 上与实际逐位一致
|
|
360
|
+
- **数量**:添加时 `amount0` / `amount1` 是按当前价格实际会用掉的(V2 与 Router 的取整一致;给了的一边可能因为取整少用几 wei),`amount0Max` / `amount1Max` 是传给合约的上限;移除时是按当前价格能拿到的(不含手续费),`fees0` / `fees1` 是一并领取的手续费
|
|
361
|
+
- **区间**:价格按 tokenB / tokenA 给,换算成池子的 tick(token1 / token0 方向,tokenA 是 token1 时自动取倒数),再取最近的可用 tick(`tickSpacing` 的整数倍);计划里的 `priceLower` / `priceUpper` 是取整后的实际区间(token1 / token0)。价格在区间外时只需要一种代币,给错了会报错并说明需要哪一种
|
|
362
|
+
- **新仓位的 tokenId**:发送后从回执里读(EVM 上主交易 confirmed 时);Tron 上为 null,用 `getLpPositions` 查
|
|
363
|
+
- 往已有仓位追加、移除、领取都会先确认发送者是仓位的所有者(V3 也可以是被授权的 operator),不是时构建就报错(V3 的合约允许任何人往别人的仓位里加流动性,tokenId 写错时代币会白送给别人)
|
|
364
|
+
- **V4 的上限可能超过给的数量**:V4 直接指定流动性,`amountMax` 是价格在滑点范围内最不利时需要的数量(与 Uniswap 的 SDK 相同),授权和附带的主币按它给,实际只扣按成交价格算的部分、主币多余的退回。主币池子要求余额够 `value`(= `amount0Max`),给的数量接近全部余额时请留出这部分或调小滑点。V3 传给合约的就是给的数量,不会超出
|
|
365
|
+
- `dryRun: true` 时如果需要授权,主交易会预估失败(授权还没上链);只想看数量用 `build*`
|
|
366
|
+
|
|
367
|
+
核对方式:EVM 在 Base 主网分叉(anvil)上真实发交易,覆盖 Uniswap V2 / V3 / V4 和 PancakeSwap V3 的新建、追加、部分移除、全部移除并销毁;Tron 以近期真实用户的身份在主网预执行(SunSwap V2 添加 / 移除、V3 移除 / 追加),结果与计划逐位核对。
|
|
368
|
+
|
|
369
|
+
**局限**:手续费转账代币(fee-on-transfer)不支持;V4 的 hooks 如果额外收取 / 返还代币,计划里的数量不含这部分(交易仍按 `amountMax` / `amountMin` 保护);PancakeSwap 质押到农场的仓位要先取出。
|
|
370
|
+
|
|
371
|
+
打包:在已经用到 `Provider` 的基础上,只用 `build*` 约增加 40KB(minify,gzip 约 13KB),加上发送约 77KB(gzip 约 26KB,其中大部分是 `/write` 的发送代码),均不含 ethers。
|
|
372
|
+
|
|
373
|
+
|
|
301
374
|
## 功能
|
|
302
375
|
|
|
303
376
|
- **常用查询**:余额、代币详情、授权额度、NFT(集合 / 持有 / 元数据地址 / ERC1155 余额,子路径 `/nft`),一个函数一次请求
|
|
@@ -655,6 +728,10 @@ await router.swap.staticCall(params, { value })
|
|
|
655
728
|
```bash
|
|
656
729
|
pnpm test # 单元测试(mock 节点,不需要网络)
|
|
657
730
|
pnpm test:live # 连真实节点:BSC / Ethereum / Tron 主网(BSC_RPC / ETH_RPC / TRON_HOST / TRON_API_KEY 可覆盖)
|
|
731
|
+
pnpm test:live:lp # LP 仓位连主网核对(Ethereum / BSC / Base)
|
|
732
|
+
pnpm test:live:liquidity # SunSwap 加减流动性:在 Tron 主网上以真实用户的地址模拟(不发送)
|
|
733
|
+
pnpm test:fork # 加减流动性在主网分叉上真实执行:先 anvil --fork-url https://mainnet.base.org --port 18545,再带 FORK_RPC=http://127.0.0.1:18545
|
|
734
|
+
pnpm demo # 本地运行 demo(demo/,直接用 src 的源码)
|
|
658
735
|
pnpm build # 编译到 dist
|
|
659
736
|
pnpm build:contracts # 修改 contracts/ 后重新生成 src/deployless.ts
|
|
660
737
|
pnpm check:rpc # 检查内置公共节点表的可用性(--chain=56 只查一条链)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Interface, type BigNumberish } from 'ethers';
|
|
2
|
+
import { type LpPosition, type LpProtocol, type LpToken, type LpVersion } from '../lp.js';
|
|
3
|
+
import type { Provider } from '../provider.js';
|
|
4
|
+
import type { LiquidityOptions, LiquidityPlan, LiquidityTx, PositionRef } from './types.js';
|
|
5
|
+
export declare const ZERO_ADDRESS: string;
|
|
6
|
+
export { MAX_UINT128 } from '../lpMath.js';
|
|
7
|
+
/** Uniswap 的 Permit2(各 EVM 链上地址相同),V4 的仓位合约通过它收取代币 */
|
|
8
|
+
export declare const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
9
|
+
export declare const erc20Interface: Interface;
|
|
10
|
+
/** 一次构建用到的公共信息 */
|
|
11
|
+
export interface Ctx {
|
|
12
|
+
provider: Provider;
|
|
13
|
+
chainId: number;
|
|
14
|
+
tron: boolean;
|
|
15
|
+
/** 0x 格式(ABI 编码用) */
|
|
16
|
+
owner: string;
|
|
17
|
+
recipient: string;
|
|
18
|
+
slippage: number;
|
|
19
|
+
/** 截止时间(秒级时间戳) */
|
|
20
|
+
deadline: number;
|
|
21
|
+
options: LiquidityOptions;
|
|
22
|
+
}
|
|
23
|
+
/** 地址统一成 0x 的校验和格式(Tron 的 T 地址先转换) */
|
|
24
|
+
export declare function evm(address: string): string;
|
|
25
|
+
export declare const same: (a: string, b: string) => boolean;
|
|
26
|
+
/** 输出的地址:Tron 上转成 T 地址 */
|
|
27
|
+
export declare function out(ctx: Pick<Ctx, 'tron'>, address: string): string;
|
|
28
|
+
export declare function createCtx(provider: Provider, owner: string, options: LiquidityOptions): Promise<Ctx>;
|
|
29
|
+
/** 是否是主币地址(NATIVE_TOKEN / 零地址,或 Provider 配置的主币地址) */
|
|
30
|
+
export declare function isNative(ctx: Ctx, address: string): boolean;
|
|
31
|
+
/** 代币信息(symbol / 精度);零地址是 V4 的主币 */
|
|
32
|
+
export declare function tokenInfo(ctx: Ctx, addresses: readonly string[]): Promise<LpToken[]>;
|
|
33
|
+
export declare function fmt(value: bigint, token: LpToken): string | null;
|
|
34
|
+
/** 解析输入的数量:amount(最小单位)和 formatted 二选一,都没给时返回 undefined */
|
|
35
|
+
export declare function parseAmount(raw: BigNumberish | undefined, formatted: string | undefined, token: LpToken, name: string): bigint | undefined;
|
|
36
|
+
/** 按滑点向下取:value × (1 − slippage) */
|
|
37
|
+
export declare function minus(value: bigint, slippage: number): bigint;
|
|
38
|
+
/** 移除的数量:percent(百分数)或 liquidity,二选一,默认全部 */
|
|
39
|
+
export declare function removeAmount(total: bigint, percent: number | undefined, liquidity: BigNumberish | undefined): bigint;
|
|
40
|
+
export declare function protocolById(ctx: Ctx, protocol: string | LpProtocol): LpProtocol;
|
|
41
|
+
/** V3 / V4 仓位所属的协议:按 positionManager 找,没有时按协议 id */
|
|
42
|
+
export declare function concentratedProtocol(ctx: Ctx, ref: PositionRef | LpPosition): LpProtocol;
|
|
43
|
+
/** 仓位是哪个版本:LpPosition 自带;PositionRef 有 tokenId 的看协议,否则是 V2 */
|
|
44
|
+
export declare function positionVersion(ctx: Ctx, ref: PositionRef | LpPosition): LpVersion;
|
|
45
|
+
export declare function tokenIdOf(ref: PositionRef | LpPosition): bigint;
|
|
46
|
+
/** ERC20 授权:额度不够时 approve(USDT 等已有非零额度时先 approve 0)。amount 为 0 的不需要 */
|
|
47
|
+
export declare function approvals(ctx: Ctx, items: ReadonlyArray<{
|
|
48
|
+
token: string;
|
|
49
|
+
spender: string;
|
|
50
|
+
amount: bigint;
|
|
51
|
+
}>): Promise<LiquidityTx[]>;
|
|
52
|
+
/** V4:代币先授权给 Permit2,再在 Permit2 里授权给仓位合约(额度不够或已过期时) */
|
|
53
|
+
export declare function permit2Approvals(ctx: Ctx, spender: string, items: ReadonlyArray<{
|
|
54
|
+
token: string;
|
|
55
|
+
amount: bigint;
|
|
56
|
+
}>): Promise<LiquidityTx[]>;
|
|
57
|
+
/** 计划里的价格字段(token1 / token0,按精度换算) */
|
|
58
|
+
export declare function priceFields(token0: LpToken, token1: LpToken, sqrtPriceX96: bigint | null, tickLower: number, tickUpper: number): {
|
|
59
|
+
price: null;
|
|
60
|
+
priceLower: null;
|
|
61
|
+
priceUpper: null;
|
|
62
|
+
} | {
|
|
63
|
+
price: number | null;
|
|
64
|
+
priceLower: number;
|
|
65
|
+
priceUpper: number;
|
|
66
|
+
};
|
|
67
|
+
type PlanInput = Omit<LiquidityPlan, 'chainId' | 'owner' | 'recipient' | 'deadline' | 'amount0Formatted' | 'amount1Formatted' | 'fees0Formatted' | 'fees1Formatted' | 'pool'> & {
|
|
68
|
+
pool: string | null;
|
|
69
|
+
};
|
|
70
|
+
/** 补上公共字段、格式化数量 */
|
|
71
|
+
export declare function makePlan(ctx: Ctx, input: PlanInput): LiquidityPlan;
|
|
72
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/liquidity/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { Interface, MaxUint256, ZeroAddress, getAddress, getBigInt, parseUnits } from 'ethers';
|
|
2
|
+
import { formatUnits } from '../erc20.js';
|
|
3
|
+
import { LP_PROTOCOLS } from '../lp.js';
|
|
4
|
+
import { sqrtPriceToPrice, tickToPrice } from '../lpMath.js';
|
|
5
|
+
import { isTronAddress, isTronChain, toEvmAddress, toTronAddress } from '../tron.js';
|
|
6
|
+
export const ZERO_ADDRESS = ZeroAddress;
|
|
7
|
+
export { MAX_UINT128 } from '../lpMath.js';
|
|
8
|
+
const MAX_UINT160 = 2n ** 160n - 1n;
|
|
9
|
+
/** Uniswap 的 Permit2(各 EVM 链上地址相同),V4 的仓位合约通过它收取代币 */
|
|
10
|
+
export const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3';
|
|
11
|
+
/** Permit2 授权的有效期:30 天(与 Uniswap 网页一致) */
|
|
12
|
+
const PERMIT2_EXPIRATION = 30 * 24 * 3600;
|
|
13
|
+
export const erc20Interface = new Interface([
|
|
14
|
+
'function allowance(address owner, address spender) view returns (uint256)',
|
|
15
|
+
'function approve(address spender, uint256 amount) returns (bool)',
|
|
16
|
+
]);
|
|
17
|
+
const permit2Interface = new Interface([
|
|
18
|
+
'function allowance(address owner, address token, address spender) view returns (uint160 amount, uint48 expiration, uint48 nonce)',
|
|
19
|
+
'function approve(address token, address spender, uint160 amount, uint48 expiration)',
|
|
20
|
+
]);
|
|
21
|
+
/** 地址统一成 0x 的校验和格式(Tron 的 T 地址先转换) */
|
|
22
|
+
export function evm(address) {
|
|
23
|
+
return getAddress(isTronAddress(address) ? toEvmAddress(address) : address);
|
|
24
|
+
}
|
|
25
|
+
export const same = (a, b) => evm(a) === evm(b);
|
|
26
|
+
/** 输出的地址:Tron 上转成 T 地址 */
|
|
27
|
+
export function out(ctx, address) {
|
|
28
|
+
return ctx.tron ? toTronAddress(address) : address;
|
|
29
|
+
}
|
|
30
|
+
export async function createCtx(provider, owner, options) {
|
|
31
|
+
const chainId = await provider.getChainId();
|
|
32
|
+
const slippage = options.slippage ?? 0.005;
|
|
33
|
+
if (!(slippage >= 0 && slippage < 1)) {
|
|
34
|
+
throw new RangeError(`slippage must be in [0, 1): ${slippage}`);
|
|
35
|
+
}
|
|
36
|
+
const seconds = options.deadline ?? 1200;
|
|
37
|
+
if (!(seconds > 0)) {
|
|
38
|
+
throw new RangeError(`deadline must be greater than 0: ${seconds}`);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
provider,
|
|
42
|
+
chainId,
|
|
43
|
+
tron: isTronChain(chainId),
|
|
44
|
+
owner: evm(owner),
|
|
45
|
+
recipient: evm(options.recipient ?? owner),
|
|
46
|
+
slippage,
|
|
47
|
+
deadline: Math.floor(Date.now() / 1000) + Math.floor(seconds),
|
|
48
|
+
options,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** 是否是主币地址(NATIVE_TOKEN / 零地址,或 Provider 配置的主币地址) */
|
|
52
|
+
export function isNative(ctx, address) {
|
|
53
|
+
return evm(address) === ZERO_ADDRESS || ctx.provider.isNativeToken(address) || ctx.provider.isNativeToken(evm(address));
|
|
54
|
+
}
|
|
55
|
+
/** 代币信息(symbol / 精度);零地址是 V4 的主币 */
|
|
56
|
+
export async function tokenInfo(ctx, addresses) {
|
|
57
|
+
const nativeAlias = ctx.provider.isNativeToken(ZERO_ADDRESS) ? undefined : ctx.provider.nativeTokens[0];
|
|
58
|
+
const query = addresses.map((a) => (a === ZERO_ADDRESS && nativeAlias !== undefined ? nativeAlias : a));
|
|
59
|
+
const details = await ctx.provider.tokens(query, { fields: ['symbol', 'decimals'] });
|
|
60
|
+
return addresses.map((address, i) => {
|
|
61
|
+
const d = details[i];
|
|
62
|
+
return { address: out(ctx, address), native: d?.native ?? false, symbol: d?.symbol ?? null, decimals: d?.decimals ?? null };
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export function fmt(value, token) {
|
|
66
|
+
return token.decimals === null ? null : formatUnits(value, token.decimals);
|
|
67
|
+
}
|
|
68
|
+
/** 解析输入的数量:amount(最小单位)和 formatted 二选一,都没给时返回 undefined */
|
|
69
|
+
export function parseAmount(raw, formatted, token, name) {
|
|
70
|
+
if (raw !== undefined && formatted !== undefined) {
|
|
71
|
+
throw new Error(`Pass either ${name} or ${name}Formatted, not both`);
|
|
72
|
+
}
|
|
73
|
+
let value;
|
|
74
|
+
if (formatted !== undefined) {
|
|
75
|
+
if (token.decimals === null) {
|
|
76
|
+
throw new Error(`Cannot read the decimals of ${token.address}; pass ${name} in raw units instead of ${name}Formatted`);
|
|
77
|
+
}
|
|
78
|
+
value = parseUnits(formatted, token.decimals);
|
|
79
|
+
}
|
|
80
|
+
else if (raw !== undefined) {
|
|
81
|
+
value = getBigInt(raw);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
if (value < 0n) {
|
|
87
|
+
throw new RangeError(`${name} must not be negative`);
|
|
88
|
+
}
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
/** 按滑点向下取:value × (1 − slippage) */
|
|
92
|
+
export function minus(value, slippage) {
|
|
93
|
+
return (value * (1000000n - BigInt(Math.round(slippage * 1e6)))) / 1000000n;
|
|
94
|
+
}
|
|
95
|
+
/** 移除的数量:percent(百分数)或 liquidity,二选一,默认全部 */
|
|
96
|
+
export function removeAmount(total, percent, liquidity) {
|
|
97
|
+
if (percent !== undefined && liquidity !== undefined) {
|
|
98
|
+
throw new Error('Pass either percent or liquidity, not both');
|
|
99
|
+
}
|
|
100
|
+
if (liquidity !== undefined) {
|
|
101
|
+
const value = getBigInt(liquidity);
|
|
102
|
+
if (value <= 0n || value > total) {
|
|
103
|
+
throw new RangeError(`liquidity must be in (0, ${total}]: ${value}`);
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
const p = percent ?? 100;
|
|
108
|
+
if (!(p > 0 && p <= 100)) {
|
|
109
|
+
throw new RangeError(`percent must be in (0, 100]: ${p}`);
|
|
110
|
+
}
|
|
111
|
+
const amount = p === 100 ? total : (total * BigInt(Math.round(p * 10_000))) / 1000000n;
|
|
112
|
+
if (amount === 0n) {
|
|
113
|
+
throw new RangeError(`${p}% of ${total} rounds to 0`);
|
|
114
|
+
}
|
|
115
|
+
return amount;
|
|
116
|
+
}
|
|
117
|
+
/** 选出协议:自定义的优先,再找内置表 */
|
|
118
|
+
function candidates(ctx) {
|
|
119
|
+
return [...(ctx.options.protocols ?? []).filter((p) => p.chainId === ctx.chainId), ...LP_PROTOCOLS.filter((p) => p.chainId === ctx.chainId)];
|
|
120
|
+
}
|
|
121
|
+
export function protocolById(ctx, protocol) {
|
|
122
|
+
if (typeof protocol !== 'string') {
|
|
123
|
+
if (protocol.chainId !== ctx.chainId) {
|
|
124
|
+
throw new Error(`Protocol ${protocol.id} is on chain ${protocol.chainId}, not ${ctx.chainId}`);
|
|
125
|
+
}
|
|
126
|
+
return protocol;
|
|
127
|
+
}
|
|
128
|
+
const found = candidates(ctx).find((p) => p.id === protocol);
|
|
129
|
+
if (!found) {
|
|
130
|
+
throw new Error(`Unknown LP protocol ${protocol} on chain ${ctx.chainId}; pass an LpProtocol object (or options.protocols) for protocols that are not built in`);
|
|
131
|
+
}
|
|
132
|
+
return found;
|
|
133
|
+
}
|
|
134
|
+
/** V3 / V4 仓位所属的协议:按 positionManager 找,没有时按协议 id */
|
|
135
|
+
export function concentratedProtocol(ctx, ref) {
|
|
136
|
+
const pm = 'positionManager' in ref && ref.positionManager ? evm(ref.positionManager) : null;
|
|
137
|
+
if (pm) {
|
|
138
|
+
const fromRef = ref.protocol && typeof ref.protocol !== 'string' ? [ref.protocol] : [];
|
|
139
|
+
const found = [...fromRef, ...candidates(ctx)].find((p) => (p.version === 'v3' || p.version === 'v4') && p.positionManager && same(p.positionManager, pm));
|
|
140
|
+
if (!found) {
|
|
141
|
+
throw new Error(`Unknown position manager ${pm} on chain ${ctx.chainId}; pass its LpProtocol in options.protocols`);
|
|
142
|
+
}
|
|
143
|
+
return found;
|
|
144
|
+
}
|
|
145
|
+
if (!ref.protocol) {
|
|
146
|
+
throw new Error('position needs positionManager or protocol');
|
|
147
|
+
}
|
|
148
|
+
const found = protocolById(ctx, ref.protocol);
|
|
149
|
+
if (found.version === 'v2') {
|
|
150
|
+
throw new Error(`${found.id} is a V2 protocol; V2 positions are identified by pool`);
|
|
151
|
+
}
|
|
152
|
+
return found;
|
|
153
|
+
}
|
|
154
|
+
/** 仓位是哪个版本:LpPosition 自带;PositionRef 有 tokenId 的看协议,否则是 V2 */
|
|
155
|
+
export function positionVersion(ctx, ref) {
|
|
156
|
+
if ('version' in ref && (ref.version === 'v2' || ref.version === 'v3' || ref.version === 'v4')) {
|
|
157
|
+
return ref.version;
|
|
158
|
+
}
|
|
159
|
+
if (!('tokenId' in ref) || ref.tokenId === undefined) {
|
|
160
|
+
if (!ref.pool) {
|
|
161
|
+
throw new Error('position needs pool (V2) or tokenId (V3 / V4)');
|
|
162
|
+
}
|
|
163
|
+
// 传了 V3 / V4 的协议却没有 tokenId:说清楚,不要当成 V2 的池子去读
|
|
164
|
+
if (ref.protocol && (typeof ref.protocol === 'string' ? protocolById(ctx, ref.protocol) : ref.protocol).version !== 'v2') {
|
|
165
|
+
throw new Error('position.tokenId is required for V3 / V4 positions');
|
|
166
|
+
}
|
|
167
|
+
return 'v2';
|
|
168
|
+
}
|
|
169
|
+
return concentratedProtocol(ctx, ref).version;
|
|
170
|
+
}
|
|
171
|
+
export function tokenIdOf(ref) {
|
|
172
|
+
if (!('tokenId' in ref) || ref.tokenId === undefined) {
|
|
173
|
+
throw new Error('position.tokenId is required');
|
|
174
|
+
}
|
|
175
|
+
if (typeof ref.tokenId === 'number' && !Number.isSafeInteger(ref.tokenId)) {
|
|
176
|
+
throw new RangeError(`tokenId ${ref.tokenId} is not a safe integer; pass it as a string or bigint`);
|
|
177
|
+
}
|
|
178
|
+
return getBigInt(ref.tokenId);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* 要求先把额度归零才能改成另一个非零值的代币(chainId:小写地址)。只对它们先 approve 0:
|
|
182
|
+
* 有的代币(如 Ethereum 上的 BNB)反过来不允许 approve 0
|
|
183
|
+
*/
|
|
184
|
+
const RESET_FIRST = new Set([
|
|
185
|
+
'1:0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
|
|
186
|
+
'1:0xdd974d5c2e2928dea5f71b9825b8b646686bd200', // KNC(旧版)
|
|
187
|
+
]);
|
|
188
|
+
/** ERC20 授权:额度不够时 approve(USDT 等已有非零额度时先 approve 0)。amount 为 0 的不需要 */
|
|
189
|
+
export async function approvals(ctx, items) {
|
|
190
|
+
const needed = items.filter((i) => i.amount > 0n);
|
|
191
|
+
if (!needed.length) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
const current = await ctx.provider.all(needed.map((i) => ctx.provider.contract(i.token, erc20Interface).allowance(ctx.owner, i.spender)));
|
|
195
|
+
return needed.flatMap((item, k) => {
|
|
196
|
+
const allowance = current[k];
|
|
197
|
+
if (allowance >= item.amount) {
|
|
198
|
+
return [];
|
|
199
|
+
}
|
|
200
|
+
const amount = ctx.options.approve === 'max' ? MaxUint256 : item.amount;
|
|
201
|
+
const tx = (value) => ({
|
|
202
|
+
kind: 'approve',
|
|
203
|
+
to: out(ctx, item.token),
|
|
204
|
+
data: erc20Interface.encodeFunctionData('approve', [item.spender, value]),
|
|
205
|
+
value: '0',
|
|
206
|
+
token: out(ctx, item.token),
|
|
207
|
+
spender: out(ctx, item.spender),
|
|
208
|
+
amount: value.toString(),
|
|
209
|
+
});
|
|
210
|
+
return allowance > 0n && RESET_FIRST.has(`${ctx.chainId}:${item.token.toLowerCase()}`) ? [tx(0n), tx(amount)] : [tx(amount)];
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/** V4:代币先授权给 Permit2,再在 Permit2 里授权给仓位合约(额度不够或已过期时) */
|
|
214
|
+
export async function permit2Approvals(ctx, spender, items) {
|
|
215
|
+
const needed = items.filter((i) => i.amount > 0n);
|
|
216
|
+
if (!needed.length) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
const erc20 = await approvals(ctx, needed.map((i) => ({ token: i.token, spender: PERMIT2_ADDRESS, amount: i.amount })));
|
|
220
|
+
const permits = (await ctx.provider.all(needed.map((i) => ctx.provider.contract(PERMIT2_ADDRESS, permit2Interface).allowance(ctx.owner, i.token, spender))));
|
|
221
|
+
const now = Math.floor(Date.now() / 1000);
|
|
222
|
+
const permit2 = needed.flatMap((item, k) => {
|
|
223
|
+
const [amount, expiration] = [permits[k]?.[0] ?? 0n, Number(permits[k]?.[1] ?? 0n)];
|
|
224
|
+
// 额度够、并且在交易截止时间之后才过期:不用再授权
|
|
225
|
+
if (amount >= item.amount && expiration >= ctx.deadline) {
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
// 过期重新授权时保留原来更大的额度(如之前授权过无限额度)
|
|
229
|
+
const value = ctx.options.approve === 'max' ? MAX_UINT160 : amount > item.amount ? amount : item.amount;
|
|
230
|
+
return [
|
|
231
|
+
{
|
|
232
|
+
kind: 'permit2',
|
|
233
|
+
to: PERMIT2_ADDRESS,
|
|
234
|
+
data: permit2Interface.encodeFunctionData('approve', [item.token, spender, value, Math.max(now, ctx.deadline) + PERMIT2_EXPIRATION]),
|
|
235
|
+
value: '0',
|
|
236
|
+
token: item.token,
|
|
237
|
+
spender,
|
|
238
|
+
amount: value.toString(),
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
});
|
|
242
|
+
return [...erc20, ...permit2];
|
|
243
|
+
}
|
|
244
|
+
/** 计划里的价格字段(token1 / token0,按精度换算) */
|
|
245
|
+
export function priceFields(token0, token1, sqrtPriceX96, tickLower, tickUpper) {
|
|
246
|
+
if (token0.decimals === null || token1.decimals === null) {
|
|
247
|
+
return { price: null, priceLower: null, priceUpper: null };
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
price: sqrtPriceX96 ? sqrtPriceToPrice(sqrtPriceX96, token0.decimals, token1.decimals) : null,
|
|
251
|
+
priceLower: tickToPrice(tickLower, token0.decimals, token1.decimals),
|
|
252
|
+
priceUpper: tickToPrice(tickUpper, token0.decimals, token1.decimals),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/** 补上公共字段、格式化数量 */
|
|
256
|
+
export function makePlan(ctx, input) {
|
|
257
|
+
const { token0, token1 } = input;
|
|
258
|
+
return {
|
|
259
|
+
...input,
|
|
260
|
+
chainId: ctx.chainId,
|
|
261
|
+
pool: input.pool === null || input.version === 'v4' ? input.pool : out(ctx, input.pool),
|
|
262
|
+
owner: out(ctx, ctx.owner),
|
|
263
|
+
recipient: out(ctx, ctx.recipient),
|
|
264
|
+
amount0Formatted: fmt(BigInt(input.amount0), token0),
|
|
265
|
+
amount1Formatted: fmt(BigInt(input.amount1), token1),
|
|
266
|
+
fees0Formatted: fmt(BigInt(input.fees0), token0),
|
|
267
|
+
fees1Formatted: fmt(BigInt(input.fees1), token1),
|
|
268
|
+
deadline: ctx.deadline,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/liquidity/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LpToken } from '../lp.js';
|
|
2
|
+
import type { NewPositionParams } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 价格(tokenB / tokenA,按精度换算)→ 池子的 sqrtPriceX96(token1 / token0)。aIs0:tokenA 是不是 token0
|
|
5
|
+
*/
|
|
6
|
+
export declare function sqrtPriceOf(price: string | number, aIs0: boolean, token0: LpToken, token1: LpToken, name: string): bigint;
|
|
7
|
+
/** 新建仓位的 tick 区间:fullRange / tickLower + tickUpper / priceLower + priceUpper 三选一 */
|
|
8
|
+
export declare function resolveRange(params: NewPositionParams, aIs0: boolean, token0: LpToken, token1: LpToken, tickSpacing: number): [number, number];
|
|
9
|
+
/**
|
|
10
|
+
* 按输入的数量算添加的流动性:两边都给时取较少的一边;只给一边时另一边按当前价格算。
|
|
11
|
+
* 价格在区间外时只需要一种代币,给错了另一种会报错
|
|
12
|
+
*/
|
|
13
|
+
export declare function liquidityFor(sqrtPrice: bigint, tickLower: number, tickUpper: number, amount0: bigint | undefined, amount1: bigint | undefined, token0: LpToken, token1: LpToken): bigint;
|
|
14
|
+
/**
|
|
15
|
+
* V3:按传给仓位合约的数量(desired),价格在滑点范围内变动时至少会用掉多少(amountMin)。
|
|
16
|
+
* 合约按当时的价格重新算流动性:token0 在价格最高时用得最少,token1 在最低时;取三个价格下的最小值
|
|
17
|
+
*/
|
|
18
|
+
export declare function v3MinAmounts(sqrtPrice: bigint, tickLower: number, tickUpper: number, desired0: bigint, desired1: bigint, slippage: number): [bigint, bigint];
|
|
19
|
+
//# sourceMappingURL=concentrated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concentrated.d.ts","sourceRoot":"","sources":["../../src/liquidity/concentrated.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAgBvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAUzH;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoC9I;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CA0BxL;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAY5J"}
|