@flaunch/sdk 0.8.3-beta.3 → 0.8.3-beta.4
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/abi/FLETH.d.ts +76 -0
- package/dist/abi/FLETH.d.ts.map +1 -0
- package/dist/addresses/index.cjs +5 -0
- package/dist/addresses/index.cjs.map +1 -1
- package/dist/addresses/index.js +5 -1
- package/dist/addresses/index.js.map +1 -1
- package/dist/addresses.d.ts +1 -0
- package/dist/addresses.d.ts.map +1 -1
- package/dist/clients/MemecoinClient.d.ts +5 -0
- package/dist/clients/MemecoinClient.d.ts.map +1 -1
- package/dist/clients/TokenImporter.d.ts.map +1 -1
- package/dist/helpers/index.cjs +5 -0
- package/dist/helpers/index.cjs.map +1 -1
- package/dist/helpers/index.js +5 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/index.cjs.js +789 -19
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +782 -21
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/sdk/FlaunchSDK.d.ts +40 -1
- package/dist/sdk/FlaunchSDK.d.ts.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/univ4.d.ts +55 -1
- package/dist/utils/univ4.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs.js
CHANGED
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var drift = require('@delvtech/drift');
|
|
6
6
|
var viem = require('viem');
|
|
7
7
|
var axios = require('axios');
|
|
8
|
-
var v3Sdk = require('@uniswap/v3-sdk');
|
|
9
8
|
var driftViem = require('@delvtech/drift-viem');
|
|
10
9
|
|
|
11
10
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -5467,6 +5466,10 @@ const Permit2Address = {
|
|
|
5467
5466
|
[base.id]: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
5468
5467
|
[baseSepolia.id]: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
|
|
5469
5468
|
};
|
|
5469
|
+
const UniV4PositionManagerAddress = {
|
|
5470
|
+
[base.id]: "0x7C5f5A4bBd8fD63184577525326123B519429bDc",
|
|
5471
|
+
[baseSepolia.id]: "0x4B2C77d209D3405F41a037Ec6c77F7F5b8e2ca80",
|
|
5472
|
+
};
|
|
5470
5473
|
const USDCETHPoolKeys = {
|
|
5471
5474
|
[base.id]: {
|
|
5472
5475
|
currency0: viem.zeroAddress,
|
|
@@ -11208,6 +11211,11 @@ exports.Verifier = void 0;
|
|
|
11208
11211
|
Verifier["WHITELIST"] = "whitelist";
|
|
11209
11212
|
Verifier["ZORA"] = "zora";
|
|
11210
11213
|
})(exports.Verifier || (exports.Verifier = {}));
|
|
11214
|
+
exports.LiquidityMode = void 0;
|
|
11215
|
+
(function (LiquidityMode) {
|
|
11216
|
+
LiquidityMode["FULL_RANGE"] = "full-range";
|
|
11217
|
+
LiquidityMode["CONCENTRATED"] = "concentrated";
|
|
11218
|
+
})(exports.LiquidityMode || (exports.LiquidityMode = {}));
|
|
11211
11219
|
/**
|
|
11212
11220
|
* Enumeration of Permissions for TreasuryManagers. Defaults to OPEN.
|
|
11213
11221
|
*/
|
|
@@ -14667,6 +14675,13 @@ class ReadMemecoin {
|
|
|
14667
14675
|
tokenURI() {
|
|
14668
14676
|
return this.contract.read("tokenURI");
|
|
14669
14677
|
}
|
|
14678
|
+
/**
|
|
14679
|
+
* Gets the decimals of the token
|
|
14680
|
+
* @returns Promise<number> - The decimals of the token
|
|
14681
|
+
*/
|
|
14682
|
+
decimals() {
|
|
14683
|
+
return this.contract.read("decimals");
|
|
14684
|
+
}
|
|
14670
14685
|
/**
|
|
14671
14686
|
* Gets the total supply of the token
|
|
14672
14687
|
* @returns Promise<bigint> - The total supply
|
|
@@ -19518,26 +19533,21 @@ class ReadWriteTokenImporter extends ReadTokenImporter {
|
|
|
19518
19533
|
constructor(chainId, address, drift$1 = drift.createDrift()) {
|
|
19519
19534
|
super(chainId, address, drift$1);
|
|
19520
19535
|
}
|
|
19521
|
-
initialize({ memecoin, creatorFeeAllocationPercent, initialMarketCapUSD, verifier, }) {
|
|
19536
|
+
async initialize({ memecoin, creatorFeeAllocationPercent, initialMarketCapUSD, verifier, }) {
|
|
19522
19537
|
const initialMCapInUSDCWei = viem.parseUnits(initialMarketCapUSD.toString(), 6);
|
|
19523
19538
|
const creatorFeeAllocationInBps = creatorFeeAllocationPercent * 100;
|
|
19524
|
-
//
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
_memecoin: memecoin,
|
|
19529
|
-
_creatorFeeAllocation: creatorFeeAllocationInBps,
|
|
19530
|
-
_initialMarketCap: initialMCapInUSDCWei,
|
|
19531
|
-
_verifier: verifierAddress,
|
|
19532
|
-
});
|
|
19533
|
-
}
|
|
19534
|
-
else {
|
|
19535
|
-
return this.contract.write("initialize", {
|
|
19539
|
+
// Passing in the verifier here, as drift doesn't recognize the other initialize function without the verifier param
|
|
19540
|
+
let _verifier = verifier
|
|
19541
|
+
? this.verifierAddress(verifier)
|
|
19542
|
+
: await this.contract.read("verifyMemecoin", {
|
|
19536
19543
|
_memecoin: memecoin,
|
|
19537
|
-
_creatorFeeAllocation: creatorFeeAllocationInBps,
|
|
19538
|
-
_initialMarketCap: initialMCapInUSDCWei,
|
|
19539
19544
|
});
|
|
19540
|
-
|
|
19545
|
+
return this.contract.write("initialize", {
|
|
19546
|
+
_memecoin: memecoin,
|
|
19547
|
+
_creatorFeeAllocation: creatorFeeAllocationInBps,
|
|
19548
|
+
_initialMarketCap: initialMCapInUSDCWei,
|
|
19549
|
+
_verifier,
|
|
19550
|
+
});
|
|
19541
19551
|
}
|
|
19542
19552
|
}
|
|
19543
19553
|
|
|
@@ -24384,6 +24394,8 @@ const TickFinder = {
|
|
|
24384
24394
|
MIN_TICK: -887220,
|
|
24385
24395
|
MAX_TICK: 887220,
|
|
24386
24396
|
};
|
|
24397
|
+
const Q96 = 2n ** 96n;
|
|
24398
|
+
const Q192 = 2n ** 192n;
|
|
24387
24399
|
const TICK_SPACING = 60;
|
|
24388
24400
|
const getPoolId = (poolKey) => {
|
|
24389
24401
|
// Pack the data in the same order as Solidity struct
|
|
@@ -24406,7 +24418,7 @@ const orderPoolKey = (poolKey) => {
|
|
|
24406
24418
|
currency1,
|
|
24407
24419
|
};
|
|
24408
24420
|
};
|
|
24409
|
-
const getValidTick = ({ tick, tickSpacing, roundDown, }) => {
|
|
24421
|
+
const getValidTick = ({ tick, tickSpacing, roundDown = true, }) => {
|
|
24410
24422
|
// If the tick is already valid, exit early
|
|
24411
24423
|
if (tick % tickSpacing === 0) {
|
|
24412
24424
|
return tick;
|
|
@@ -24423,6 +24435,11 @@ const getValidTick = ({ tick, tickSpacing, roundDown, }) => {
|
|
|
24423
24435
|
}
|
|
24424
24436
|
return validTick;
|
|
24425
24437
|
};
|
|
24438
|
+
// Rounds up or down to the nearest tick
|
|
24439
|
+
const getNearestUsableTick = ({ tick, tickSpacing, }) => {
|
|
24440
|
+
const rounded = Math.round(tick / tickSpacing) * tickSpacing;
|
|
24441
|
+
return Math.max(TickFinder.MIN_TICK, Math.min(TickFinder.MAX_TICK, rounded));
|
|
24442
|
+
};
|
|
24426
24443
|
const getAmount0ForLiquidity = (sqrtRatioAX96, sqrtRatioBX96, liquidity) => {
|
|
24427
24444
|
let [sqrtRatioA, sqrtRatioB] = [sqrtRatioAX96, sqrtRatioBX96];
|
|
24428
24445
|
if (sqrtRatioA > sqrtRatioB) {
|
|
@@ -24446,7 +24463,60 @@ const getAmount1ForLiquidity = (sqrtRatioAX96, sqrtRatioBX96, liquidity) => {
|
|
|
24446
24463
|
return amount1;
|
|
24447
24464
|
};
|
|
24448
24465
|
const getSqrtPriceX96FromTick = (tick) => {
|
|
24449
|
-
|
|
24466
|
+
const absTick = tick < 0 ? BigInt(-tick) : BigInt(tick);
|
|
24467
|
+
if (absTick > TickFinder.MAX_TICK) {
|
|
24468
|
+
throw new Error("Tick out of range");
|
|
24469
|
+
}
|
|
24470
|
+
let ratio = (absTick & 1n) !== 0n
|
|
24471
|
+
? 0xfffcb933bd6fad37aa2d162d1a594001n
|
|
24472
|
+
: 0x100000000000000000000000000000000n;
|
|
24473
|
+
if ((absTick & 2n) !== 0n)
|
|
24474
|
+
ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n;
|
|
24475
|
+
if ((absTick & 4n) !== 0n)
|
|
24476
|
+
ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n;
|
|
24477
|
+
if ((absTick & 8n) !== 0n)
|
|
24478
|
+
ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n;
|
|
24479
|
+
if ((absTick & 16n) !== 0n)
|
|
24480
|
+
ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n;
|
|
24481
|
+
if ((absTick & 32n) !== 0n)
|
|
24482
|
+
ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n;
|
|
24483
|
+
if ((absTick & 64n) !== 0n)
|
|
24484
|
+
ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n;
|
|
24485
|
+
if ((absTick & 128n) !== 0n)
|
|
24486
|
+
ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n;
|
|
24487
|
+
if ((absTick & 256n) !== 0n)
|
|
24488
|
+
ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n;
|
|
24489
|
+
if ((absTick & 512n) !== 0n)
|
|
24490
|
+
ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n;
|
|
24491
|
+
if ((absTick & 1024n) !== 0n)
|
|
24492
|
+
ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n;
|
|
24493
|
+
if ((absTick & 2048n) !== 0n)
|
|
24494
|
+
ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n;
|
|
24495
|
+
if ((absTick & 4096n) !== 0n)
|
|
24496
|
+
ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n;
|
|
24497
|
+
if ((absTick & 8192n) !== 0n)
|
|
24498
|
+
ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n;
|
|
24499
|
+
if ((absTick & 16384n) !== 0n)
|
|
24500
|
+
ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n;
|
|
24501
|
+
if ((absTick & 32768n) !== 0n)
|
|
24502
|
+
ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n;
|
|
24503
|
+
if ((absTick & 65536n) !== 0n)
|
|
24504
|
+
ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n;
|
|
24505
|
+
if ((absTick & 131072n) !== 0n)
|
|
24506
|
+
ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n;
|
|
24507
|
+
if ((absTick & 262144n) !== 0n)
|
|
24508
|
+
ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n;
|
|
24509
|
+
if ((absTick & 524288n) !== 0n)
|
|
24510
|
+
ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n;
|
|
24511
|
+
if (tick > 0) {
|
|
24512
|
+
ratio = (2n ** 256n - 1n) / ratio;
|
|
24513
|
+
}
|
|
24514
|
+
// Convert from Q128.128 to Q128.96
|
|
24515
|
+
const resultShifted = ratio >> 32n;
|
|
24516
|
+
if (ratio % (1n << 32n) === 0n) {
|
|
24517
|
+
return resultShifted;
|
|
24518
|
+
}
|
|
24519
|
+
return resultShifted + 1n;
|
|
24450
24520
|
};
|
|
24451
24521
|
const calculateUnderlyingTokenBalances = (liquidity, tickLower, tickUpper, tickCurrent) => {
|
|
24452
24522
|
const sqrtPriceCurrentX96 = getSqrtPriceX96FromTick(tickCurrent);
|
|
@@ -24469,6 +24539,137 @@ const calculateUnderlyingTokenBalances = (liquidity, tickLower, tickUpper, tickC
|
|
|
24469
24539
|
}
|
|
24470
24540
|
return { amount0, amount1 };
|
|
24471
24541
|
};
|
|
24542
|
+
// Helper function to convert price ratio to tick with decimal handling
|
|
24543
|
+
const priceRatioToTick = ({ priceInput, isDirection1Per0, decimals0, decimals1, spacing, shouldGetNearestUsableTick = true, }) => {
|
|
24544
|
+
if (!priceInput || isNaN(Number(priceInput)))
|
|
24545
|
+
return 0;
|
|
24546
|
+
const inputPrice = Number(priceInput);
|
|
24547
|
+
try {
|
|
24548
|
+
// For Uniswap v3/v4, the tick represents price as: price = 1.0001^tick
|
|
24549
|
+
// where price = amount1/amount0 in their raw decimal format
|
|
24550
|
+
let priceRatio;
|
|
24551
|
+
if (isDirection1Per0) {
|
|
24552
|
+
// Input is token1 per token0 (e.g., memecoin per flETH)
|
|
24553
|
+
// Convert from human-readable to raw: divide by (10^decimals0 / 10^decimals1)
|
|
24554
|
+
priceRatio = inputPrice / Math.pow(10, decimals0 - decimals1);
|
|
24555
|
+
}
|
|
24556
|
+
else {
|
|
24557
|
+
// Input is token0 per token1 (e.g., flETH per memecoin)
|
|
24558
|
+
// Invert to get token1 per token0, then convert to raw
|
|
24559
|
+
priceRatio = 1 / inputPrice / Math.pow(10, decimals0 - decimals1);
|
|
24560
|
+
}
|
|
24561
|
+
// Calculate tick: tick = log(price) / log(1.0001)
|
|
24562
|
+
const tick = Math.log(priceRatio) / Math.log(1.0001);
|
|
24563
|
+
if (shouldGetNearestUsableTick) {
|
|
24564
|
+
return getValidTick({
|
|
24565
|
+
tick: Math.round(tick),
|
|
24566
|
+
tickSpacing: spacing,
|
|
24567
|
+
});
|
|
24568
|
+
}
|
|
24569
|
+
else {
|
|
24570
|
+
return Math.round(tick);
|
|
24571
|
+
}
|
|
24572
|
+
}
|
|
24573
|
+
catch (error) {
|
|
24574
|
+
console.error("Error converting price to tick:", error);
|
|
24575
|
+
// Fallback to basic calculation
|
|
24576
|
+
const rawTick = Math.floor(Math.log(inputPrice) / Math.log(1.0001));
|
|
24577
|
+
if (shouldGetNearestUsableTick) {
|
|
24578
|
+
return getValidTick({
|
|
24579
|
+
tick: rawTick,
|
|
24580
|
+
tickSpacing: spacing,
|
|
24581
|
+
});
|
|
24582
|
+
}
|
|
24583
|
+
else {
|
|
24584
|
+
return rawTick;
|
|
24585
|
+
}
|
|
24586
|
+
}
|
|
24587
|
+
};
|
|
24588
|
+
/**
|
|
24589
|
+
* Accurate liquidity calculation using proper Uniswap v3/v4 math
|
|
24590
|
+
*/
|
|
24591
|
+
const getLiquidityFromAmounts = (params) => {
|
|
24592
|
+
const sqrtRatioCurrentX96 = getSqrtPriceX96FromTick(params.currentTick);
|
|
24593
|
+
let sqrtRatioAX96 = getSqrtPriceX96FromTick(params.tickLower);
|
|
24594
|
+
let sqrtRatioBX96 = getSqrtPriceX96FromTick(params.tickUpper);
|
|
24595
|
+
if (sqrtRatioAX96 > sqrtRatioBX96) {
|
|
24596
|
+
[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96];
|
|
24597
|
+
}
|
|
24598
|
+
if (sqrtRatioCurrentX96 <= sqrtRatioAX96) {
|
|
24599
|
+
return maxLiquidityForAmount0Precise(sqrtRatioAX96, sqrtRatioBX96, params.amount0);
|
|
24600
|
+
}
|
|
24601
|
+
else if (sqrtRatioCurrentX96 < sqrtRatioBX96) {
|
|
24602
|
+
const liquidity0 = maxLiquidityForAmount0Precise(sqrtRatioCurrentX96, sqrtRatioBX96, params.amount0);
|
|
24603
|
+
const liquidity1 = maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioCurrentX96, params.amount1);
|
|
24604
|
+
return liquidity0 < liquidity1 ? liquidity0 : liquidity1;
|
|
24605
|
+
}
|
|
24606
|
+
else {
|
|
24607
|
+
return maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, params.amount1);
|
|
24608
|
+
}
|
|
24609
|
+
};
|
|
24610
|
+
/**
|
|
24611
|
+
* Returns a precise maximum amount of liquidity received for a given amount of token 0 by dividing by Q64 instead of Q96 in the intermediate step,
|
|
24612
|
+
* and shifting the subtracted ratio left by 32 bits.
|
|
24613
|
+
* @param sqrtRatioAX96 The price at the lower boundary
|
|
24614
|
+
* @param sqrtRatioBX96 The price at the upper boundary
|
|
24615
|
+
* @param amount0 The token0 amount
|
|
24616
|
+
* @returns liquidity for amount0, precise
|
|
24617
|
+
*/
|
|
24618
|
+
function maxLiquidityForAmount0Precise(sqrtRatioAX96, sqrtRatioBX96, amount0) {
|
|
24619
|
+
if (sqrtRatioAX96 > sqrtRatioBX96) {
|
|
24620
|
+
[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96];
|
|
24621
|
+
}
|
|
24622
|
+
const Q96 = 2n ** 96n;
|
|
24623
|
+
const numerator = amount0 * sqrtRatioAX96 * sqrtRatioBX96;
|
|
24624
|
+
const denominator = Q96 * (sqrtRatioBX96 - sqrtRatioAX96);
|
|
24625
|
+
return numerator / denominator;
|
|
24626
|
+
}
|
|
24627
|
+
/**
|
|
24628
|
+
* Computes the maximum amount of liquidity received for a given amount of token1
|
|
24629
|
+
* @param sqrtRatioAX96 The price at the lower tick boundary
|
|
24630
|
+
* @param sqrtRatioBX96 The price at the upper tick boundary
|
|
24631
|
+
* @param amount1 The token1 amount
|
|
24632
|
+
* @returns liquidity for amount1
|
|
24633
|
+
*/
|
|
24634
|
+
function maxLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1) {
|
|
24635
|
+
if (sqrtRatioAX96 > sqrtRatioBX96) {
|
|
24636
|
+
[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96];
|
|
24637
|
+
}
|
|
24638
|
+
const Q96 = 2n ** 96n;
|
|
24639
|
+
return (amount1 * Q96) / (sqrtRatioBX96 - sqrtRatioAX96);
|
|
24640
|
+
}
|
|
24641
|
+
/**
|
|
24642
|
+
* Calculate the actual amounts needed for a given liquidity
|
|
24643
|
+
* This prevents MaximumAmountExceeded errors by ensuring we provide sufficient maximums
|
|
24644
|
+
*/
|
|
24645
|
+
const getAmountsForLiquidity = (params) => {
|
|
24646
|
+
// Handle zero liquidity case
|
|
24647
|
+
if (params.liquidity === 0n) {
|
|
24648
|
+
return { amount0: 0n, amount1: 0n };
|
|
24649
|
+
}
|
|
24650
|
+
const sqrtRatioCurrentX96 = getSqrtPriceX96FromTick(params.currentTick);
|
|
24651
|
+
let sqrtRatioAX96 = getSqrtPriceX96FromTick(params.tickLower);
|
|
24652
|
+
let sqrtRatioBX96 = getSqrtPriceX96FromTick(params.tickUpper);
|
|
24653
|
+
if (sqrtRatioAX96 > sqrtRatioBX96) {
|
|
24654
|
+
[sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96];
|
|
24655
|
+
}
|
|
24656
|
+
let amount0 = 0n;
|
|
24657
|
+
let amount1 = 0n;
|
|
24658
|
+
if (sqrtRatioCurrentX96 <= sqrtRatioAX96) {
|
|
24659
|
+
// Current price is below the range, only token0 needed
|
|
24660
|
+
amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, params.liquidity);
|
|
24661
|
+
}
|
|
24662
|
+
else if (sqrtRatioCurrentX96 < sqrtRatioBX96) {
|
|
24663
|
+
// Current price is within the range, need both tokens
|
|
24664
|
+
amount0 = getAmount0ForLiquidity(sqrtRatioCurrentX96, sqrtRatioBX96, params.liquidity);
|
|
24665
|
+
amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioCurrentX96, params.liquidity);
|
|
24666
|
+
}
|
|
24667
|
+
else {
|
|
24668
|
+
// Current price is above the range, only token1 needed
|
|
24669
|
+
amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, params.liquidity);
|
|
24670
|
+
}
|
|
24671
|
+
return { amount0, amount1 };
|
|
24672
|
+
};
|
|
24472
24673
|
|
|
24473
24674
|
const FastFlaunchZapAbi = [
|
|
24474
24675
|
{
|
|
@@ -24533,6 +24734,58 @@ const FastFlaunchZapAbi = [
|
|
|
24533
24734
|
},
|
|
24534
24735
|
];
|
|
24535
24736
|
|
|
24737
|
+
const FLETHAbi = [
|
|
24738
|
+
{
|
|
24739
|
+
inputs: [{ internalType: "uint256", name: "wethAmount", type: "uint256" }],
|
|
24740
|
+
name: "deposit",
|
|
24741
|
+
outputs: [],
|
|
24742
|
+
stateMutability: "payable",
|
|
24743
|
+
type: "function",
|
|
24744
|
+
},
|
|
24745
|
+
{
|
|
24746
|
+
inputs: [{ internalType: "uint256", name: "amount", type: "uint256" }],
|
|
24747
|
+
name: "withdraw",
|
|
24748
|
+
outputs: [],
|
|
24749
|
+
stateMutability: "nonpayable",
|
|
24750
|
+
type: "function",
|
|
24751
|
+
},
|
|
24752
|
+
{
|
|
24753
|
+
inputs: [{ internalType: "address", name: "account", type: "address" }],
|
|
24754
|
+
name: "balanceOf",
|
|
24755
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
24756
|
+
stateMutability: "view",
|
|
24757
|
+
type: "function",
|
|
24758
|
+
},
|
|
24759
|
+
{
|
|
24760
|
+
inputs: [],
|
|
24761
|
+
name: "totalSupply",
|
|
24762
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
24763
|
+
stateMutability: "view",
|
|
24764
|
+
type: "function",
|
|
24765
|
+
},
|
|
24766
|
+
{
|
|
24767
|
+
inputs: [],
|
|
24768
|
+
name: "name",
|
|
24769
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
24770
|
+
stateMutability: "view",
|
|
24771
|
+
type: "function",
|
|
24772
|
+
},
|
|
24773
|
+
{
|
|
24774
|
+
inputs: [],
|
|
24775
|
+
name: "symbol",
|
|
24776
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
24777
|
+
stateMutability: "view",
|
|
24778
|
+
type: "function",
|
|
24779
|
+
},
|
|
24780
|
+
{
|
|
24781
|
+
inputs: [],
|
|
24782
|
+
name: "decimals",
|
|
24783
|
+
outputs: [{ internalType: "uint8", name: "", type: "uint8" }],
|
|
24784
|
+
stateMutability: "view",
|
|
24785
|
+
type: "function",
|
|
24786
|
+
},
|
|
24787
|
+
];
|
|
24788
|
+
|
|
24536
24789
|
/**
|
|
24537
24790
|
* Base class for interacting with Flaunch protocol in read-only mode
|
|
24538
24791
|
*/
|
|
@@ -25336,6 +25589,177 @@ class ReadFlaunchSDK {
|
|
|
25336
25589
|
tokenImporterVerifyMemecoin(memecoin) {
|
|
25337
25590
|
return this.readTokenImporter.verifyMemecoin(memecoin);
|
|
25338
25591
|
}
|
|
25592
|
+
async calculateAddLiquidityTicks({ coinAddress, liquidityMode, minMarketCap, maxMarketCap, }) {
|
|
25593
|
+
const memecoin = new ReadMemecoin(coinAddress, this.drift);
|
|
25594
|
+
const coinTotalSupply = await memecoin.totalSupply();
|
|
25595
|
+
const coinDecimals = await memecoin.decimals();
|
|
25596
|
+
if (liquidityMode === exports.LiquidityMode.FULL_RANGE) {
|
|
25597
|
+
return {
|
|
25598
|
+
tickLower: getNearestUsableTick({
|
|
25599
|
+
tick: TickFinder.MIN_TICK,
|
|
25600
|
+
tickSpacing: TICK_SPACING,
|
|
25601
|
+
}),
|
|
25602
|
+
tickUpper: getNearestUsableTick({
|
|
25603
|
+
tick: TickFinder.MAX_TICK,
|
|
25604
|
+
tickSpacing: TICK_SPACING,
|
|
25605
|
+
}),
|
|
25606
|
+
coinTotalSupply,
|
|
25607
|
+
coinDecimals,
|
|
25608
|
+
};
|
|
25609
|
+
}
|
|
25610
|
+
else {
|
|
25611
|
+
const ethUsdPrice = await this.getETHUSDCPrice();
|
|
25612
|
+
const isFlethZero = this.flETHIsCurrencyZero(coinAddress);
|
|
25613
|
+
const minMarketCapNum = parseFloat(minMarketCap);
|
|
25614
|
+
const maxMarketCapNum = parseFloat(maxMarketCap);
|
|
25615
|
+
if (minMarketCapNum <= 0 ||
|
|
25616
|
+
maxMarketCapNum <= 0 ||
|
|
25617
|
+
minMarketCapNum >= maxMarketCapNum) {
|
|
25618
|
+
throw new Error("[ReadFlaunchSDK.addLiquidityCalculateTicks]: Invalid market cap range");
|
|
25619
|
+
}
|
|
25620
|
+
// Convert total supply to decimal format
|
|
25621
|
+
const totalSupplyDecimal = parseFloat(viem.formatEther(coinTotalSupply));
|
|
25622
|
+
// Calculate token price in USD at min and max market caps
|
|
25623
|
+
const minTokenPriceUsd = minMarketCapNum / totalSupplyDecimal;
|
|
25624
|
+
const maxTokenPriceUsd = maxMarketCapNum / totalSupplyDecimal;
|
|
25625
|
+
// Convert to token price in ETH
|
|
25626
|
+
const minTokenPriceEth = minTokenPriceUsd / ethUsdPrice;
|
|
25627
|
+
const maxTokenPriceEth = maxTokenPriceUsd / ethUsdPrice;
|
|
25628
|
+
const flETHDecimals = 18; // flETH has 18 decimals
|
|
25629
|
+
// Determine decimals based on token ordering
|
|
25630
|
+
const decimals0 = isFlethZero ? flETHDecimals : coinDecimals;
|
|
25631
|
+
const decimals1 = isFlethZero ? coinDecimals : flETHDecimals;
|
|
25632
|
+
// Convert to ticks using proper price direction handling
|
|
25633
|
+
const minTick = priceRatioToTick({
|
|
25634
|
+
priceInput: minTokenPriceEth.toString(),
|
|
25635
|
+
isDirection1Per0: !isFlethZero,
|
|
25636
|
+
decimals0,
|
|
25637
|
+
decimals1,
|
|
25638
|
+
spacing: TICK_SPACING,
|
|
25639
|
+
});
|
|
25640
|
+
const maxTick = priceRatioToTick({
|
|
25641
|
+
priceInput: maxTokenPriceEth.toString(),
|
|
25642
|
+
isDirection1Per0: !isFlethZero,
|
|
25643
|
+
decimals0,
|
|
25644
|
+
decimals1,
|
|
25645
|
+
spacing: TICK_SPACING,
|
|
25646
|
+
});
|
|
25647
|
+
return {
|
|
25648
|
+
tickLower: Math.min(minTick, maxTick),
|
|
25649
|
+
tickUpper: Math.max(minTick, maxTick),
|
|
25650
|
+
coinTotalSupply,
|
|
25651
|
+
coinDecimals,
|
|
25652
|
+
};
|
|
25653
|
+
}
|
|
25654
|
+
}
|
|
25655
|
+
async calculateAddLiquidityAmounts({ coinAddress, liquidityMode, coinOrEthInputAmount, inputToken, minMarketCap, maxMarketCap, }) {
|
|
25656
|
+
const { tickLower, tickUpper } = await this.calculateAddLiquidityTicks({
|
|
25657
|
+
coinAddress,
|
|
25658
|
+
liquidityMode,
|
|
25659
|
+
minMarketCap,
|
|
25660
|
+
maxMarketCap,
|
|
25661
|
+
});
|
|
25662
|
+
// get the current pool state for AnyPositionManager pool for the coin
|
|
25663
|
+
const poolState = await this.readStateView.poolSlot0({
|
|
25664
|
+
poolId: getPoolId(orderPoolKey({
|
|
25665
|
+
currency0: coinAddress,
|
|
25666
|
+
currency1: FLETHAddress[this.chainId],
|
|
25667
|
+
fee: 0,
|
|
25668
|
+
tickSpacing: TICK_SPACING,
|
|
25669
|
+
hooks: AnyPositionManagerAddress[this.chainId],
|
|
25670
|
+
})),
|
|
25671
|
+
});
|
|
25672
|
+
const currentTick = poolState.tick;
|
|
25673
|
+
// Determine currency ordering
|
|
25674
|
+
const isFlETHCurrency0 = this.flETHIsCurrencyZero(coinAddress);
|
|
25675
|
+
try {
|
|
25676
|
+
const sqrtRatioCurrentX96 = getSqrtPriceX96FromTick(currentTick);
|
|
25677
|
+
let sqrtRatioLowerX96 = getSqrtPriceX96FromTick(tickLower);
|
|
25678
|
+
let sqrtRatioUpperX96 = getSqrtPriceX96FromTick(tickUpper);
|
|
25679
|
+
if (sqrtRatioLowerX96 > sqrtRatioUpperX96) {
|
|
25680
|
+
[sqrtRatioLowerX96, sqrtRatioUpperX96] = [
|
|
25681
|
+
sqrtRatioUpperX96,
|
|
25682
|
+
sqrtRatioLowerX96,
|
|
25683
|
+
];
|
|
25684
|
+
}
|
|
25685
|
+
let amount0Calculated;
|
|
25686
|
+
let amount1Calculated;
|
|
25687
|
+
// Determine which calculation to use based on input token and currency ordering
|
|
25688
|
+
const isCoinInput = inputToken === "coin";
|
|
25689
|
+
const inputAmount = coinOrEthInputAmount;
|
|
25690
|
+
if ((isCoinInput && !isFlETHCurrency0) || // coin input and coin is currency0
|
|
25691
|
+
(!isCoinInput && isFlETHCurrency0) // eth input and flETH is currency0
|
|
25692
|
+
) {
|
|
25693
|
+
// We have amount0 and need to calculate amount1
|
|
25694
|
+
amount0Calculated = inputAmount;
|
|
25695
|
+
if (sqrtRatioCurrentX96 <= sqrtRatioLowerX96) {
|
|
25696
|
+
// Current price below range - no currency1 needed
|
|
25697
|
+
amount1Calculated = 0n;
|
|
25698
|
+
}
|
|
25699
|
+
else if (sqrtRatioCurrentX96 >= sqrtRatioUpperX96) {
|
|
25700
|
+
// Current price above range - proportional amount1 needed
|
|
25701
|
+
const ratio = (sqrtRatioUpperX96 * sqrtRatioUpperX96) / Q96;
|
|
25702
|
+
amount1Calculated = (inputAmount * ratio) / Q96;
|
|
25703
|
+
}
|
|
25704
|
+
else {
|
|
25705
|
+
// Current price in range - proportional amounts
|
|
25706
|
+
const intermediate1 = (sqrtRatioUpperX96 *
|
|
25707
|
+
sqrtRatioCurrentX96 *
|
|
25708
|
+
(sqrtRatioCurrentX96 - sqrtRatioLowerX96)) /
|
|
25709
|
+
Q96;
|
|
25710
|
+
const intermediate2 = (Q192 * (sqrtRatioUpperX96 - sqrtRatioCurrentX96)) / Q96;
|
|
25711
|
+
if (intermediate2 > 0n) {
|
|
25712
|
+
amount1Calculated = (inputAmount * intermediate1) / intermediate2;
|
|
25713
|
+
}
|
|
25714
|
+
else {
|
|
25715
|
+
amount1Calculated = 0n;
|
|
25716
|
+
}
|
|
25717
|
+
}
|
|
25718
|
+
}
|
|
25719
|
+
else {
|
|
25720
|
+
// We have amount1 and need to calculate amount0
|
|
25721
|
+
amount1Calculated = inputAmount;
|
|
25722
|
+
if (sqrtRatioCurrentX96 <= sqrtRatioLowerX96) {
|
|
25723
|
+
// Current price below range - proportional amount0 needed
|
|
25724
|
+
const ratio = (sqrtRatioLowerX96 * sqrtRatioLowerX96) / Q96;
|
|
25725
|
+
amount0Calculated = (inputAmount * Q96) / ratio;
|
|
25726
|
+
}
|
|
25727
|
+
else if (sqrtRatioCurrentX96 >= sqrtRatioUpperX96) {
|
|
25728
|
+
// Current price above range - no amount0 needed
|
|
25729
|
+
amount0Calculated = 0n;
|
|
25730
|
+
}
|
|
25731
|
+
else {
|
|
25732
|
+
// Current price in range - proportional amounts
|
|
25733
|
+
const intermediate1 = (sqrtRatioUpperX96 *
|
|
25734
|
+
sqrtRatioCurrentX96 *
|
|
25735
|
+
(sqrtRatioCurrentX96 - sqrtRatioLowerX96)) /
|
|
25736
|
+
Q96;
|
|
25737
|
+
const intermediate2 = (Q192 * (sqrtRatioUpperX96 - sqrtRatioCurrentX96)) / Q96;
|
|
25738
|
+
if (intermediate1 > 0n) {
|
|
25739
|
+
amount0Calculated = (inputAmount * intermediate2) / intermediate1;
|
|
25740
|
+
}
|
|
25741
|
+
else {
|
|
25742
|
+
amount0Calculated = 0n;
|
|
25743
|
+
}
|
|
25744
|
+
}
|
|
25745
|
+
}
|
|
25746
|
+
// Map amount0/amount1 back to coin/eth amounts based on currency ordering
|
|
25747
|
+
const [ethAmount, coinAmount] = isFlETHCurrency0
|
|
25748
|
+
? [amount0Calculated, amount1Calculated]
|
|
25749
|
+
: [amount1Calculated, amount0Calculated];
|
|
25750
|
+
return {
|
|
25751
|
+
coinAmount,
|
|
25752
|
+
ethAmount,
|
|
25753
|
+
tickLower,
|
|
25754
|
+
tickUpper,
|
|
25755
|
+
currentTick,
|
|
25756
|
+
};
|
|
25757
|
+
}
|
|
25758
|
+
catch (error) {
|
|
25759
|
+
console.error("Error calculating liquidity amounts:", error);
|
|
25760
|
+
throw error;
|
|
25761
|
+
}
|
|
25762
|
+
}
|
|
25339
25763
|
/**
|
|
25340
25764
|
* Checks if an operator is approved for all flaunch tokens of an owner
|
|
25341
25765
|
* @param version - The flaunch version to determine the correct contract address
|
|
@@ -25715,6 +26139,343 @@ class ReadWriteFlaunchSDK extends ReadFlaunchSDK {
|
|
|
25715
26139
|
importMemecoin(params) {
|
|
25716
26140
|
return this.readWriteTokenImporter.initialize(params);
|
|
25717
26141
|
}
|
|
26142
|
+
async getAddLiquidityCalls(params) {
|
|
26143
|
+
const { coinAddress } = params;
|
|
26144
|
+
const flethAddress = FLETHAddress[this.chainId];
|
|
26145
|
+
let coinAmount;
|
|
26146
|
+
let flethAmount;
|
|
26147
|
+
let tickLower;
|
|
26148
|
+
let tickUpper;
|
|
26149
|
+
let currentTick;
|
|
26150
|
+
const poolKey = orderPoolKey({
|
|
26151
|
+
currency0: coinAddress,
|
|
26152
|
+
currency1: flethAddress,
|
|
26153
|
+
fee: 0,
|
|
26154
|
+
tickSpacing: this.TICK_SPACING,
|
|
26155
|
+
hooks: AnyPositionManagerAddress[this.chainId],
|
|
26156
|
+
});
|
|
26157
|
+
// Check if we need to calculate values or use direct values
|
|
26158
|
+
if ("tickLower" in params) {
|
|
26159
|
+
// Use the directly provided values
|
|
26160
|
+
coinAmount = params.coinAmount;
|
|
26161
|
+
flethAmount = params.flethAmount;
|
|
26162
|
+
tickLower = params.tickLower;
|
|
26163
|
+
tickUpper = params.tickUpper;
|
|
26164
|
+
const poolState = await this.readStateView.poolSlot0({
|
|
26165
|
+
poolId: getPoolId(poolKey),
|
|
26166
|
+
});
|
|
26167
|
+
currentTick = poolState.tick;
|
|
26168
|
+
}
|
|
26169
|
+
else {
|
|
26170
|
+
// Calculate the amounts
|
|
26171
|
+
const calculated = await this.calculateAddLiquidityAmounts({
|
|
26172
|
+
coinAddress,
|
|
26173
|
+
liquidityMode: params.liquidityMode,
|
|
26174
|
+
coinOrEthInputAmount: params.coinOrEthInputAmount,
|
|
26175
|
+
inputToken: params.inputToken,
|
|
26176
|
+
minMarketCap: params.minMarketCap,
|
|
26177
|
+
maxMarketCap: params.maxMarketCap,
|
|
26178
|
+
});
|
|
26179
|
+
coinAmount = calculated.coinAmount;
|
|
26180
|
+
flethAmount = calculated.ethAmount;
|
|
26181
|
+
tickLower = calculated.tickLower;
|
|
26182
|
+
tickUpper = calculated.tickUpper;
|
|
26183
|
+
currentTick = calculated.currentTick;
|
|
26184
|
+
}
|
|
26185
|
+
// Fetch approvals via multicall
|
|
26186
|
+
const userAddress = await this.drift.getSignerAddress();
|
|
26187
|
+
const permit2Address = Permit2Address[this.chainId];
|
|
26188
|
+
const results = await this.drift.multicall({
|
|
26189
|
+
calls: [
|
|
26190
|
+
// coin -> permit2
|
|
26191
|
+
{
|
|
26192
|
+
address: coinAddress,
|
|
26193
|
+
abi: viem.erc20Abi,
|
|
26194
|
+
fn: "allowance",
|
|
26195
|
+
args: {
|
|
26196
|
+
owner: userAddress,
|
|
26197
|
+
spender: permit2Address,
|
|
26198
|
+
},
|
|
26199
|
+
},
|
|
26200
|
+
// flETH -> permit2
|
|
26201
|
+
{
|
|
26202
|
+
address: flethAddress,
|
|
26203
|
+
abi: viem.erc20Abi,
|
|
26204
|
+
fn: "allowance",
|
|
26205
|
+
args: {
|
|
26206
|
+
owner: userAddress,
|
|
26207
|
+
spender: permit2Address,
|
|
26208
|
+
},
|
|
26209
|
+
},
|
|
26210
|
+
// coin --permit2--> uni position manager
|
|
26211
|
+
{
|
|
26212
|
+
address: permit2Address,
|
|
26213
|
+
abi: Permit2Abi,
|
|
26214
|
+
fn: "allowance",
|
|
26215
|
+
args: {
|
|
26216
|
+
0: userAddress,
|
|
26217
|
+
1: coinAddress,
|
|
26218
|
+
2: UniV4PositionManagerAddress[this.chainId],
|
|
26219
|
+
},
|
|
26220
|
+
},
|
|
26221
|
+
// flETH --permit2--> uni position manager
|
|
26222
|
+
{
|
|
26223
|
+
address: permit2Address,
|
|
26224
|
+
abi: Permit2Abi,
|
|
26225
|
+
fn: "allowance",
|
|
26226
|
+
args: {
|
|
26227
|
+
0: userAddress,
|
|
26228
|
+
1: flethAddress,
|
|
26229
|
+
2: UniV4PositionManagerAddress[this.chainId],
|
|
26230
|
+
},
|
|
26231
|
+
},
|
|
26232
|
+
// coin symbol
|
|
26233
|
+
{
|
|
26234
|
+
address: coinAddress,
|
|
26235
|
+
abi: viem.erc20Abi,
|
|
26236
|
+
fn: "symbol",
|
|
26237
|
+
},
|
|
26238
|
+
],
|
|
26239
|
+
});
|
|
26240
|
+
const coinToPermit2 = results[0].value;
|
|
26241
|
+
const flethToPermit2 = results[1].value;
|
|
26242
|
+
const permit2ToUniPosManagerCoinAllowance = results[2].value;
|
|
26243
|
+
const permit2ToUniPosManagerFlethAllowance = results[3].value;
|
|
26244
|
+
const coinSymbol = results[4].value;
|
|
26245
|
+
const needsCoinApproval = coinToPermit2 < coinAmount;
|
|
26246
|
+
const needsFlethApproval = flethToPermit2 < flethAmount;
|
|
26247
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
26248
|
+
const needsCoinPermit2Approval = permit2ToUniPosManagerCoinAllowance.amount < coinAmount ||
|
|
26249
|
+
permit2ToUniPosManagerCoinAllowance.expiration <= currentTime;
|
|
26250
|
+
const needsFlethPermit2Approval = flethAmount > 0n &&
|
|
26251
|
+
(permit2ToUniPosManagerFlethAllowance.amount < flethAmount ||
|
|
26252
|
+
permit2ToUniPosManagerFlethAllowance.expiration <= currentTime);
|
|
26253
|
+
const calls = [];
|
|
26254
|
+
// 1. Coin approval to Permit2
|
|
26255
|
+
if (needsCoinApproval) {
|
|
26256
|
+
calls.push({
|
|
26257
|
+
to: coinAddress,
|
|
26258
|
+
description: `Approve ${coinSymbol} for Permit2`,
|
|
26259
|
+
data: viem.encodeFunctionData({
|
|
26260
|
+
abi: viem.erc20Abi,
|
|
26261
|
+
functionName: "approve",
|
|
26262
|
+
args: [permit2Address, coinAmount],
|
|
26263
|
+
}),
|
|
26264
|
+
});
|
|
26265
|
+
}
|
|
26266
|
+
// 2. flETH approval to Permit2 (after wrapping)
|
|
26267
|
+
if (needsFlethApproval) {
|
|
26268
|
+
calls.push({
|
|
26269
|
+
to: flethAddress,
|
|
26270
|
+
description: `Approve flETH for Permit2`,
|
|
26271
|
+
data: viem.encodeFunctionData({
|
|
26272
|
+
abi: viem.erc20Abi,
|
|
26273
|
+
functionName: "approve",
|
|
26274
|
+
args: [permit2Address, flethAmount],
|
|
26275
|
+
}),
|
|
26276
|
+
});
|
|
26277
|
+
}
|
|
26278
|
+
// 3. Permit2 approval for coin to uni position manager
|
|
26279
|
+
const expiration = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now
|
|
26280
|
+
if (needsCoinPermit2Approval) {
|
|
26281
|
+
calls.push({
|
|
26282
|
+
to: permit2Address,
|
|
26283
|
+
description: `Permit2 approval for ${coinSymbol} to UniV4PositionManager`,
|
|
26284
|
+
data: viem.encodeFunctionData({
|
|
26285
|
+
abi: Permit2Abi,
|
|
26286
|
+
functionName: "approve",
|
|
26287
|
+
args: [
|
|
26288
|
+
coinAddress,
|
|
26289
|
+
UniV4PositionManagerAddress[this.chainId],
|
|
26290
|
+
coinAmount,
|
|
26291
|
+
expiration,
|
|
26292
|
+
],
|
|
26293
|
+
}),
|
|
26294
|
+
});
|
|
26295
|
+
}
|
|
26296
|
+
// 4. Permit2 approval for flETH to uni position manager
|
|
26297
|
+
if (needsFlethPermit2Approval) {
|
|
26298
|
+
calls.push({
|
|
26299
|
+
to: permit2Address,
|
|
26300
|
+
description: `Permit2 approval for flETH to UniV4PositionManager`,
|
|
26301
|
+
data: viem.encodeFunctionData({
|
|
26302
|
+
abi: Permit2Abi,
|
|
26303
|
+
functionName: "approve",
|
|
26304
|
+
args: [
|
|
26305
|
+
flethAddress,
|
|
26306
|
+
UniV4PositionManagerAddress[this.chainId],
|
|
26307
|
+
flethAmount,
|
|
26308
|
+
expiration,
|
|
26309
|
+
],
|
|
26310
|
+
}),
|
|
26311
|
+
});
|
|
26312
|
+
}
|
|
26313
|
+
// 5. Wrap ETH to flETH
|
|
26314
|
+
if (flethAmount > 0n) {
|
|
26315
|
+
calls.push({
|
|
26316
|
+
to: flethAddress,
|
|
26317
|
+
description: "Wrap ETH to flETH",
|
|
26318
|
+
data: viem.encodeFunctionData({
|
|
26319
|
+
abi: FLETHAbi,
|
|
26320
|
+
functionName: "deposit",
|
|
26321
|
+
args: [0n], // wethAmount = 0, we're only sending ETH
|
|
26322
|
+
}),
|
|
26323
|
+
value: flethAmount,
|
|
26324
|
+
});
|
|
26325
|
+
}
|
|
26326
|
+
// === generate add liquidity call ===
|
|
26327
|
+
// Determine amounts for each currency based on pool key ordering
|
|
26328
|
+
const amount0 = poolKey.currency0 === coinAddress ? coinAmount : flethAmount;
|
|
26329
|
+
const amount1 = poolKey.currency0 === coinAddress ? flethAmount : coinAmount;
|
|
26330
|
+
// Calculate liquidity first using user's input amounts
|
|
26331
|
+
const initialLiquidity = getLiquidityFromAmounts({
|
|
26332
|
+
currentTick,
|
|
26333
|
+
tickLower,
|
|
26334
|
+
tickUpper,
|
|
26335
|
+
amount0,
|
|
26336
|
+
amount1,
|
|
26337
|
+
});
|
|
26338
|
+
// Calculate the actual amounts needed for this liquidity
|
|
26339
|
+
const actualAmounts = getAmountsForLiquidity({
|
|
26340
|
+
currentTick,
|
|
26341
|
+
tickLower,
|
|
26342
|
+
tickUpper,
|
|
26343
|
+
liquidity: initialLiquidity,
|
|
26344
|
+
});
|
|
26345
|
+
// Check if actual amounts exceed user input - if so, constrain them
|
|
26346
|
+
let finalLiquidity = initialLiquidity;
|
|
26347
|
+
let finalAmount0 = actualAmounts.amount0;
|
|
26348
|
+
let finalAmount1 = actualAmounts.amount1;
|
|
26349
|
+
// If actual amounts exceed user input, we need to recalculate with constraints
|
|
26350
|
+
if (actualAmounts.amount0 > amount0 || actualAmounts.amount1 > amount1) {
|
|
26351
|
+
console.log("Actual amounts exceed user input, constraining...");
|
|
26352
|
+
// Calculate liquidity constrained by each amount separately
|
|
26353
|
+
const liquidity0Constrained = getLiquidityFromAmounts({
|
|
26354
|
+
currentTick,
|
|
26355
|
+
tickLower,
|
|
26356
|
+
tickUpper,
|
|
26357
|
+
amount0,
|
|
26358
|
+
amount1: 0n, // Only constrain by amount0
|
|
26359
|
+
});
|
|
26360
|
+
const liquidity1Constrained = getLiquidityFromAmounts({
|
|
26361
|
+
currentTick,
|
|
26362
|
+
tickLower,
|
|
26363
|
+
tickUpper,
|
|
26364
|
+
amount0: 0n, // Only constrain by amount1
|
|
26365
|
+
amount1,
|
|
26366
|
+
});
|
|
26367
|
+
// Use the smaller liquidity to ensure we don't exceed either amount
|
|
26368
|
+
finalLiquidity =
|
|
26369
|
+
liquidity0Constrained < liquidity1Constrained
|
|
26370
|
+
? liquidity0Constrained
|
|
26371
|
+
: liquidity1Constrained;
|
|
26372
|
+
// Recalculate amounts for the constrained liquidity
|
|
26373
|
+
const constrainedAmounts = getAmountsForLiquidity({
|
|
26374
|
+
currentTick,
|
|
26375
|
+
tickLower,
|
|
26376
|
+
tickUpper,
|
|
26377
|
+
liquidity: finalLiquidity,
|
|
26378
|
+
});
|
|
26379
|
+
finalAmount0 = constrainedAmounts.amount0;
|
|
26380
|
+
finalAmount1 = constrainedAmounts.amount1;
|
|
26381
|
+
}
|
|
26382
|
+
// IMPORTANT: Add conservative buffer to account for contract rounding differences
|
|
26383
|
+
// Reduce liquidity by 0.01% to ensure contract calculations stay within user bounds
|
|
26384
|
+
const liquidityBuffer = finalLiquidity / 10000n; // 0.01%
|
|
26385
|
+
const conservativeLiquidity = finalLiquidity - (liquidityBuffer > 1n ? liquidityBuffer : 1n);
|
|
26386
|
+
// Use conservative liquidity but keep user's original amounts as maximums
|
|
26387
|
+
// The conservative liquidity ensures the contract won't need more than user provided
|
|
26388
|
+
if (currentTick !== undefined) {
|
|
26389
|
+
// If pool is already initialized then use conservative liquidity
|
|
26390
|
+
// as a new pool would accept any liquidity amounts given by us
|
|
26391
|
+
finalLiquidity = conservativeLiquidity;
|
|
26392
|
+
}
|
|
26393
|
+
finalAmount0 = amount0; // Use user's full amount as maximum
|
|
26394
|
+
finalAmount1 = amount1; // Use user's full amount as maximum
|
|
26395
|
+
// Prepare mint position parameters (following swiss-knife pattern)
|
|
26396
|
+
const V4PMActions = {
|
|
26397
|
+
MINT_POSITION: "02",
|
|
26398
|
+
SETTLE_PAIR: "0d",
|
|
26399
|
+
};
|
|
26400
|
+
const v4Actions = ("0x" +
|
|
26401
|
+
V4PMActions.MINT_POSITION +
|
|
26402
|
+
V4PMActions.SETTLE_PAIR);
|
|
26403
|
+
// Validate hookData format
|
|
26404
|
+
const validHookData = "0x"; // Empty hook data for now
|
|
26405
|
+
const UniV4PM_MintPositionAbi = [
|
|
26406
|
+
{
|
|
26407
|
+
type: "tuple",
|
|
26408
|
+
components: [
|
|
26409
|
+
{ type: "address", name: "currency0" },
|
|
26410
|
+
{ type: "address", name: "currency1" },
|
|
26411
|
+
{ type: "uint24", name: "fee" },
|
|
26412
|
+
{ type: "int24", name: "tickSpacing" },
|
|
26413
|
+
{ type: "address", name: "hooks" },
|
|
26414
|
+
],
|
|
26415
|
+
},
|
|
26416
|
+
{ type: "int24", name: "tickLower" },
|
|
26417
|
+
{ type: "int24", name: "tickUpper" },
|
|
26418
|
+
{ type: "uint256", name: "liquidity" },
|
|
26419
|
+
{ type: "uint128", name: "amount0Max" },
|
|
26420
|
+
{ type: "uint128", name: "amount1Max" },
|
|
26421
|
+
{ type: "address", name: "owner" },
|
|
26422
|
+
{ type: "bytes", name: "hookData" },
|
|
26423
|
+
];
|
|
26424
|
+
const UniV4PM_SettlePairAbi = [
|
|
26425
|
+
{
|
|
26426
|
+
type: "tuple",
|
|
26427
|
+
components: [
|
|
26428
|
+
{ type: "address", name: "currency0" },
|
|
26429
|
+
{ type: "address", name: "currency1" },
|
|
26430
|
+
],
|
|
26431
|
+
},
|
|
26432
|
+
];
|
|
26433
|
+
const mintPositionParams = viem.encodeAbiParameters(UniV4PM_MintPositionAbi, [
|
|
26434
|
+
poolKey,
|
|
26435
|
+
tickLower,
|
|
26436
|
+
tickUpper,
|
|
26437
|
+
finalLiquidity,
|
|
26438
|
+
finalAmount0,
|
|
26439
|
+
finalAmount1,
|
|
26440
|
+
userAddress,
|
|
26441
|
+
validHookData,
|
|
26442
|
+
]);
|
|
26443
|
+
const settlePairParams = viem.encodeAbiParameters(UniV4PM_SettlePairAbi, [
|
|
26444
|
+
{
|
|
26445
|
+
currency0: poolKey.currency0,
|
|
26446
|
+
currency1: poolKey.currency1,
|
|
26447
|
+
},
|
|
26448
|
+
]);
|
|
26449
|
+
// 6. Add liquidity
|
|
26450
|
+
calls.push({
|
|
26451
|
+
to: UniV4PositionManagerAddress[this.chainId],
|
|
26452
|
+
data: viem.encodeFunctionData({
|
|
26453
|
+
abi: [
|
|
26454
|
+
{
|
|
26455
|
+
inputs: [
|
|
26456
|
+
{ internalType: "bytes", name: "unlockData", type: "bytes" },
|
|
26457
|
+
{ internalType: "uint256", name: "deadline", type: "uint256" },
|
|
26458
|
+
],
|
|
26459
|
+
name: "modifyLiquidities",
|
|
26460
|
+
outputs: [],
|
|
26461
|
+
stateMutability: "payable",
|
|
26462
|
+
type: "function",
|
|
26463
|
+
},
|
|
26464
|
+
],
|
|
26465
|
+
functionName: "modifyLiquidities",
|
|
26466
|
+
args: [
|
|
26467
|
+
viem.encodeAbiParameters([
|
|
26468
|
+
{ type: "bytes", name: "actions" },
|
|
26469
|
+
{ type: "bytes[]", name: "params" },
|
|
26470
|
+
], [v4Actions, [mintPositionParams, settlePairParams]]),
|
|
26471
|
+
BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 hour deadline
|
|
26472
|
+
],
|
|
26473
|
+
}),
|
|
26474
|
+
value: 0n,
|
|
26475
|
+
description: "Add Liquidity",
|
|
26476
|
+
});
|
|
26477
|
+
return calls;
|
|
26478
|
+
}
|
|
25718
26479
|
}
|
|
25719
26480
|
|
|
25720
26481
|
/**
|
|
@@ -25804,6 +26565,8 @@ exports.Permit2Abi = Permit2Abi;
|
|
|
25804
26565
|
exports.Permit2Address = Permit2Address;
|
|
25805
26566
|
exports.PoolManagerAbi = PoolManagerAbi;
|
|
25806
26567
|
exports.PoolManagerAddress = PoolManagerAddress;
|
|
26568
|
+
exports.Q192 = Q192;
|
|
26569
|
+
exports.Q96 = Q96;
|
|
25807
26570
|
exports.QuoterAbi = QuoterAbi;
|
|
25808
26571
|
exports.QuoterAddress = QuoterAddress;
|
|
25809
26572
|
exports.ReadFlaunchSDK = ReadFlaunchSDK;
|
|
@@ -25821,6 +26584,7 @@ exports.TokenImporterAddress = TokenImporterAddress;
|
|
|
25821
26584
|
exports.TreasuryManagerFactoryAbi = TreasuryManagerFactoryAbi;
|
|
25822
26585
|
exports.TreasuryManagerFactoryAddress = TreasuryManagerFactoryAddress;
|
|
25823
26586
|
exports.USDCETHPoolKeys = USDCETHPoolKeys;
|
|
26587
|
+
exports.UniV4PositionManagerAddress = UniV4PositionManagerAddress;
|
|
25824
26588
|
exports.UniversalRouterAbi = UniversalRouterAbi;
|
|
25825
26589
|
exports.UniversalRouterAddress = UniversalRouterAddress;
|
|
25826
26590
|
exports.VirtualsVerifierAddress = VirtualsVerifierAddress;
|
|
@@ -25835,14 +26599,20 @@ exports.createFlaunch = createFlaunch;
|
|
|
25835
26599
|
exports.ethToMemecoin = ethToMemecoin;
|
|
25836
26600
|
exports.generateTokenUri = generateTokenUri;
|
|
25837
26601
|
exports.getAmountWithSlippage = getAmountWithSlippage;
|
|
26602
|
+
exports.getAmountsForLiquidity = getAmountsForLiquidity;
|
|
26603
|
+
exports.getLiquidityFromAmounts = getLiquidityFromAmounts;
|
|
26604
|
+
exports.getNearestUsableTick = getNearestUsableTick;
|
|
25838
26605
|
exports.getPermissionsAddress = getPermissionsAddress;
|
|
25839
26606
|
exports.getPermit2TypedData = getPermit2TypedData;
|
|
25840
26607
|
exports.getPoolId = getPoolId;
|
|
25841
26608
|
exports.getSqrtPriceX96FromTick = getSqrtPriceX96FromTick;
|
|
25842
26609
|
exports.getValidTick = getValidTick;
|
|
26610
|
+
exports.maxLiquidityForAmount0Precise = maxLiquidityForAmount0Precise;
|
|
26611
|
+
exports.maxLiquidityForAmount1 = maxLiquidityForAmount1;
|
|
25843
26612
|
exports.memecoinToEthWithPermit2 = memecoinToEthWithPermit2;
|
|
25844
26613
|
exports.orderPoolKey = orderPoolKey;
|
|
25845
26614
|
exports.parseSwapData = parseSwapData;
|
|
26615
|
+
exports.priceRatioToTick = priceRatioToTick;
|
|
25846
26616
|
exports.resolveIPFS = resolveIPFS;
|
|
25847
26617
|
exports.uint256ToBytes32 = uint256ToBytes32;
|
|
25848
26618
|
exports.uploadFileToIPFS = uploadFileToIPFS;
|