liquid-sdk 1.7.1 → 1.7.3

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/index.d.ts CHANGED
@@ -63,6 +63,21 @@ interface VaultExtensionParams {
63
63
  /** Vesting duration in seconds after lockup ends (0 = no vesting, tokens unlock all at once) */
64
64
  vestingDuration?: number;
65
65
  }
66
+ interface AirdropExtensionParams {
67
+ /** Address allowed to `updateAdmin`, `updateMerkleRoot` (under conditions),
68
+ * and `adminClaim` the remainder after claim expiration. */
69
+ admin: Address;
70
+ /** Merkle root over leaves `keccak256(bytes.concat(keccak256(abi.encode(
71
+ * recipient, allocatedAmount))))`. Double-hashed per OZ convention. */
72
+ merkleRoot: Hex;
73
+ /** Percentage of supply to reserve for the airdrop, in BPS (1–9000). */
74
+ allocationBps: number;
75
+ /** Lockup in seconds before any recipient can claim. Min 86400 (1 day). */
76
+ lockupDuration: number;
77
+ /** Linear vesting after lockup. 0 = instant claim of full entitlement at
78
+ * lockup end. */
79
+ vestingDuration?: number;
80
+ }
66
81
  interface DeployTokenParams {
67
82
  name: string;
68
83
  symbol: string;
@@ -270,6 +285,29 @@ declare class LiquidSDK {
270
285
  * ```
271
286
  */
272
287
  buildVaultExtension(vault: VaultExtensionParams): ExtensionConfig;
288
+ /**
289
+ * Build an ExtensionConfig that reserves a percentage of supply into
290
+ * the LiquidAirdropV2 contract for merkle-tree-based distribution.
291
+ *
292
+ * The airdrop contract expects `AirdropV2ExtensionData`:
293
+ * { address admin, bytes32 merkleRoot, uint256 lockupDuration, uint256 vestingDuration }
294
+ *
295
+ * Leaf encoding used by LiquidAirdropV2.claim (note: **double hashed**
296
+ * — OZ's standard 2nd-preimage-resistant pattern):
297
+ * leaf = keccak256(bytes.concat(keccak256(abi.encode(recipient, allocatedAmount))))
298
+ *
299
+ * @example
300
+ * ```typescript
301
+ * const airdropExt = sdk.buildAirdropExtension({
302
+ * admin: account.address,
303
+ * merkleRoot: "0x…",
304
+ * allocationBps: 2000, // 20%
305
+ * lockupDuration: 86400, // 1 day (minimum)
306
+ * vestingDuration: 0, // instant claim after lockup
307
+ * });
308
+ * ```
309
+ */
310
+ buildAirdropExtension(airdrop: AirdropExtensionParams): ExtensionConfig;
273
311
  /**
274
312
  * Validate a DeploymentConfig before sending to the contract.
275
313
  * Catches common mistakes client-side with clear error messages.
@@ -289,9 +327,25 @@ declare class LiquidSDK {
289
327
  getPoolFeeState(poolId: Hex, hookAddress?: Address): Promise<PoolDynamicFeeVars>;
290
328
  getPoolCreationTimestamp(poolId: Hex, hookAddress?: Address): Promise<bigint>;
291
329
  isLiquidToken0(poolId: Hex, hookAddress?: Address): Promise<boolean>;
292
- getAvailableFees(feeOwner: Address, tokenAddress: Address): Promise<bigint>;
293
- getFeesToClaim(feeOwner: Address, tokenAddress: Address): Promise<bigint>;
294
- claimFees(feeOwner: Address, tokenAddress: Address): Promise<Hash>;
330
+ /**
331
+ * Get uncollected fees for a fee owner.
332
+ * @param feeOwner - Address that receives fees (reward recipient)
333
+ * @param feeToken - The token fees are denominated in. Defaults to WETH
334
+ * (correct for all pools using LP_LOCKER_FEE_CONVERSION).
335
+ */
336
+ getAvailableFees(feeOwner: Address, feeToken?: Address): Promise<bigint>;
337
+ /**
338
+ * Get collected, claimable fees for a fee owner.
339
+ * @param feeOwner - Address that receives fees (reward recipient)
340
+ * @param feeToken - The token fees are denominated in. Defaults to WETH.
341
+ */
342
+ getFeesToClaim(feeOwner: Address, feeToken?: Address): Promise<bigint>;
343
+ /**
344
+ * Claim all accumulated fees for a fee owner.
345
+ * @param feeOwner - Address that receives fees (reward recipient)
346
+ * @param feeToken - The token fees are denominated in. Defaults to WETH.
347
+ */
348
+ claimFees(feeOwner: Address, feeToken?: Address): Promise<Hash>;
295
349
  getVaultAllocation(tokenAddress: Address): Promise<VaultAllocation>;
296
350
  getVaultClaimable(tokenAddress: Address): Promise<bigint>;
297
351
  claimVault(tokenAddress: Address): Promise<Hash>;
@@ -473,7 +527,7 @@ declare const POOL_POSITIONS: {
473
527
  */
474
528
  declare const DEFAULTS: {
475
529
  readonly HOOK: `0x${string}`;
476
- /** LP Locker with fee conversion (converts fees to ETH before distributing) */
530
+ /** LP Locker with fee conversion (converts fees to WETH before distributing) */
477
531
  readonly LOCKER: `0x${string}`;
478
532
  readonly TICK_SPACING: 200;
479
533
  readonly TICK_IF_TOKEN0_IS_LIQUID: -230400;
@@ -2480,7 +2534,7 @@ declare enum FeePreference {
2480
2534
  *
2481
2535
  * @example
2482
2536
  * ```ts
2483
- * // Single recipient, fees converted to ETH
2537
+ * // Single recipient, fees converted to WETH
2484
2538
  * const lockerData = encodeFeeConversionLockerData([FeePreference.Paired]);
2485
2539
  *
2486
2540
  * // Two recipients: first gets ETH, second gets the token
@@ -2541,4 +2595,4 @@ declare function parseContext(contextString: string): LiquidContext | null;
2541
2595
  */
2542
2596
  declare function parseMetadata(metadataString: string): LiquidMetadata | null;
2543
2597
 
2544
- export { ADDRESSES, type AirdropInfo, type BidInAuctionParams, type BidInAuctionResult, DEFAULTS, DEFAULT_CHAIN, DEFAULT_CHAIN_ID, DEFAULT_RPC_URL, DEFAULT_TRANCHES_USD, type DeployTokenParams, type DeployTokenResult, type DeploymentConfig, type DeploymentInfo, type DevBuyParams, type DynamicFeeConfig, ERC20Abi, EXTERNAL, type ExtensionConfig, FEE, FeePreference, type GetTokensOptions, LiquidAirdropV2Abi, type LiquidContext, LiquidFactoryAbi, LiquidFeeLockerAbi, LiquidHookDynamicFeeV2Abi, LiquidLpLockerAbi, type LiquidMetadata, LiquidMevBlockDelayAbi, LiquidMevDescendingFeesAbi, LiquidPoolExtensionAllowlistAbi, LiquidSDK, type LiquidSDKConfig, LiquidSniperAuctionV2Abi, LiquidSniperUtilV2Abi, LiquidTokenAbi, LiquidUniv4EthDevBuyAbi, LiquidVaultAbi, type LockerConfig, type MarketCapTranche, type MarketCapTrancheUSD, type MevModuleConfig, POOL_POSITIONS, type PoolConfig, type PoolDynamicConfigVars, type PoolDynamicFeeVars, type PoolKey, type PoolPosition, type PositionArrays, type PositionConfig, type SniperAuctionConfig, type SniperAuctionFeeConfig, type SniperAuctionState, type SocialMediaUrl, TOKEN, type TokenConfig, type TokenCreatedEvent, type TokenRewardInfo, type VaultAllocation, type VaultExtensionParams, buildContext, buildMetadata, createDefaultPositions, createPositions, createPositionsUSD, describePositions, encodeDynamicFeePoolData, encodeFeeConversionLockerData, encodeSniperAuctionData, encodeStaticFeePoolData, getTickFromMarketCapETH, getTickFromMarketCapStable, getTickFromMarketCapUSD, marketCapFromTickETH, marketCapFromTickUSD, parseContext, parseMetadata };
2598
+ export { ADDRESSES, type AirdropExtensionParams, type AirdropInfo, type BidInAuctionParams, type BidInAuctionResult, DEFAULTS, DEFAULT_CHAIN, DEFAULT_CHAIN_ID, DEFAULT_RPC_URL, DEFAULT_TRANCHES_USD, type DeployTokenParams, type DeployTokenResult, type DeploymentConfig, type DeploymentInfo, type DevBuyParams, type DynamicFeeConfig, ERC20Abi, EXTERNAL, type ExtensionConfig, FEE, FeePreference, type GetTokensOptions, LiquidAirdropV2Abi, type LiquidContext, LiquidFactoryAbi, LiquidFeeLockerAbi, LiquidHookDynamicFeeV2Abi, LiquidLpLockerAbi, type LiquidMetadata, LiquidMevBlockDelayAbi, LiquidMevDescendingFeesAbi, LiquidPoolExtensionAllowlistAbi, LiquidSDK, type LiquidSDKConfig, LiquidSniperAuctionV2Abi, LiquidSniperUtilV2Abi, LiquidTokenAbi, LiquidUniv4EthDevBuyAbi, LiquidVaultAbi, type LockerConfig, type MarketCapTranche, type MarketCapTrancheUSD, type MevModuleConfig, POOL_POSITIONS, type PoolConfig, type PoolDynamicConfigVars, type PoolDynamicFeeVars, type PoolKey, type PoolPosition, type PositionArrays, type PositionConfig, type SniperAuctionConfig, type SniperAuctionFeeConfig, type SniperAuctionState, type SocialMediaUrl, TOKEN, type TokenConfig, type TokenCreatedEvent, type TokenRewardInfo, type VaultAllocation, type VaultExtensionParams, buildContext, buildMetadata, createDefaultPositions, createPositions, createPositionsUSD, describePositions, encodeDynamicFeePoolData, encodeFeeConversionLockerData, encodeSniperAuctionData, encodeStaticFeePoolData, getTickFromMarketCapETH, getTickFromMarketCapStable, getTickFromMarketCapUSD, marketCapFromTickETH, marketCapFromTickUSD, parseContext, parseMetadata };
package/dist/index.js CHANGED
@@ -161,7 +161,7 @@ var POOL_POSITIONS = {
161
161
  };
162
162
  var DEFAULTS = {
163
163
  HOOK: ADDRESSES.HOOK_STATIC_FEE_V2,
164
- /** LP Locker with fee conversion (converts fees to ETH before distributing) */
164
+ /** LP Locker with fee conversion (converts fees to WETH before distributing) */
165
165
  LOCKER: ADDRESSES.LP_LOCKER_FEE_CONVERSION,
166
166
  TICK_SPACING: 200,
167
167
  TICK_IF_TOKEN0_IS_LIQUID: -230400,
@@ -1201,6 +1201,73 @@ var LiquidSDK = class {
1201
1201
  extensionData
1202
1202
  };
1203
1203
  }
1204
+ // ── Airdrop Extension ──────────────────────────────────────────
1205
+ /**
1206
+ * Build an ExtensionConfig that reserves a percentage of supply into
1207
+ * the LiquidAirdropV2 contract for merkle-tree-based distribution.
1208
+ *
1209
+ * The airdrop contract expects `AirdropV2ExtensionData`:
1210
+ * { address admin, bytes32 merkleRoot, uint256 lockupDuration, uint256 vestingDuration }
1211
+ *
1212
+ * Leaf encoding used by LiquidAirdropV2.claim (note: **double hashed**
1213
+ * — OZ's standard 2nd-preimage-resistant pattern):
1214
+ * leaf = keccak256(bytes.concat(keccak256(abi.encode(recipient, allocatedAmount))))
1215
+ *
1216
+ * @example
1217
+ * ```typescript
1218
+ * const airdropExt = sdk.buildAirdropExtension({
1219
+ * admin: account.address,
1220
+ * merkleRoot: "0x…",
1221
+ * allocationBps: 2000, // 20%
1222
+ * lockupDuration: 86400, // 1 day (minimum)
1223
+ * vestingDuration: 0, // instant claim after lockup
1224
+ * });
1225
+ * ```
1226
+ */
1227
+ buildAirdropExtension(airdrop) {
1228
+ const MIN_LOCKUP = 86400;
1229
+ const MAX_BPS = 9e3;
1230
+ if (airdrop.allocationBps < 1 || airdrop.allocationBps > MAX_BPS) {
1231
+ throw new Error(
1232
+ `Airdrop allocationBps must be 1\u2013${MAX_BPS} (0.01%\u201390%). Got ${airdrop.allocationBps}.`
1233
+ );
1234
+ }
1235
+ if (airdrop.lockupDuration < MIN_LOCKUP) {
1236
+ throw new Error(
1237
+ `Airdrop lockupDuration must be \u2265 ${MIN_LOCKUP} seconds (1 day). Got ${airdrop.lockupDuration}.`
1238
+ );
1239
+ }
1240
+ if (airdrop.vestingDuration !== void 0 && airdrop.vestingDuration < 0) {
1241
+ throw new Error("Airdrop vestingDuration cannot be negative.");
1242
+ }
1243
+ const extensionData = (0, import_viem2.encodeAbiParameters)(
1244
+ [
1245
+ {
1246
+ type: "tuple",
1247
+ components: [
1248
+ { type: "address", name: "admin" },
1249
+ { type: "bytes32", name: "merkleRoot" },
1250
+ { type: "uint256", name: "lockupDuration" },
1251
+ { type: "uint256", name: "vestingDuration" }
1252
+ ]
1253
+ }
1254
+ ],
1255
+ [
1256
+ {
1257
+ admin: airdrop.admin,
1258
+ merkleRoot: airdrop.merkleRoot,
1259
+ lockupDuration: BigInt(airdrop.lockupDuration),
1260
+ vestingDuration: BigInt(airdrop.vestingDuration ?? 0)
1261
+ }
1262
+ ]
1263
+ );
1264
+ return {
1265
+ extension: ADDRESSES.AIRDROP_V2,
1266
+ msgValue: 0n,
1267
+ extensionBps: airdrop.allocationBps,
1268
+ extensionData
1269
+ };
1270
+ }
1204
1271
  // ── Validation ─────────────────────────────────────────────────
1205
1272
  /**
1206
1273
  * Validate a DeploymentConfig before sending to the contract.
@@ -1365,13 +1432,27 @@ var LiquidSDK = class {
1365
1432
  (sum, ext) => sum + ext.msgValue,
1366
1433
  0n
1367
1434
  );
1435
+ let gas;
1436
+ try {
1437
+ const estimated = await this.publicClient.estimateContractGas({
1438
+ address: ADDRESSES.FACTORY,
1439
+ abi: LiquidFactoryAbi,
1440
+ functionName: "deployToken",
1441
+ args: [deploymentConfig],
1442
+ value: msgValue,
1443
+ account: this.walletClient.account
1444
+ });
1445
+ gas = estimated * 120n / 100n;
1446
+ } catch {
1447
+ gas = 6000000n;
1448
+ }
1368
1449
  const txHash = await this.walletClient.writeContract({
1369
1450
  address: ADDRESSES.FACTORY,
1370
1451
  abi: LiquidFactoryAbi,
1371
1452
  functionName: "deployToken",
1372
1453
  args: [deploymentConfig],
1373
1454
  value: msgValue,
1374
- gas: 5000000n,
1455
+ gas,
1375
1456
  chain: import_chains2.base,
1376
1457
  account: this.walletClient.account
1377
1458
  });
@@ -1528,23 +1609,39 @@ var LiquidSDK = class {
1528
1609
  });
1529
1610
  }
1530
1611
  // ── Fee Claims ────────────────────────────────────────────────────
1531
- async getAvailableFees(feeOwner, tokenAddress) {
1612
+ /**
1613
+ * Get uncollected fees for a fee owner.
1614
+ * @param feeOwner - Address that receives fees (reward recipient)
1615
+ * @param feeToken - The token fees are denominated in. Defaults to WETH
1616
+ * (correct for all pools using LP_LOCKER_FEE_CONVERSION).
1617
+ */
1618
+ async getAvailableFees(feeOwner, feeToken = EXTERNAL.WETH) {
1532
1619
  return await this.publicClient.readContract({
1533
1620
  address: ADDRESSES.FEE_LOCKER,
1534
1621
  abi: LiquidFeeLockerAbi,
1535
1622
  functionName: "availableFees",
1536
- args: [feeOwner, tokenAddress]
1623
+ args: [feeOwner, feeToken]
1537
1624
  });
1538
1625
  }
1539
- async getFeesToClaim(feeOwner, tokenAddress) {
1626
+ /**
1627
+ * Get collected, claimable fees for a fee owner.
1628
+ * @param feeOwner - Address that receives fees (reward recipient)
1629
+ * @param feeToken - The token fees are denominated in. Defaults to WETH.
1630
+ */
1631
+ async getFeesToClaim(feeOwner, feeToken = EXTERNAL.WETH) {
1540
1632
  return await this.publicClient.readContract({
1541
1633
  address: ADDRESSES.FEE_LOCKER,
1542
1634
  abi: LiquidFeeLockerAbi,
1543
1635
  functionName: "feesToClaim",
1544
- args: [feeOwner, tokenAddress]
1636
+ args: [feeOwner, feeToken]
1545
1637
  });
1546
1638
  }
1547
- async claimFees(feeOwner, tokenAddress) {
1639
+ /**
1640
+ * Claim all accumulated fees for a fee owner.
1641
+ * @param feeOwner - Address that receives fees (reward recipient)
1642
+ * @param feeToken - The token fees are denominated in. Defaults to WETH.
1643
+ */
1644
+ async claimFees(feeOwner, feeToken = EXTERNAL.WETH) {
1548
1645
  if (!this.walletClient?.account) {
1549
1646
  throw new Error("walletClient with account required for claimFees");
1550
1647
  }
@@ -1552,7 +1649,7 @@ var LiquidSDK = class {
1552
1649
  address: ADDRESSES.FEE_LOCKER,
1553
1650
  abi: LiquidFeeLockerAbi,
1554
1651
  functionName: "claim",
1555
- args: [feeOwner, tokenAddress],
1652
+ args: [feeOwner, feeToken],
1556
1653
  chain: import_chains2.base,
1557
1654
  account: this.walletClient.account
1558
1655
  });