liquid-sdk 1.7.2 → 1.7.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/index.mjs CHANGED
@@ -34,6 +34,9 @@ var ADDRESSES = {
34
34
  var EXTERNAL = {
35
35
  POOL_MANAGER: "0x498581fF718922c3f8e6A244956aF099B2652b2b",
36
36
  WETH: "0x4200000000000000000000000000000000000006",
37
+ /** DIEM — Liquid's intelligence-economy token. Also a pair token for
38
+ * agent-token launches (see `createLiquidPositionsUSD`). */
39
+ DIEM: "0xF4d97F2da56e8c3098f3a8D538DB630A2606a024",
37
40
  UNIVERSAL_ROUTER: "0x6fF5693b99212Da76ad316178A184AB56D299b43",
38
41
  PERMIT2: "0x000000000022D473030F116dDEE9F6B43aC78BA3"
39
42
  };
@@ -103,7 +106,7 @@ var POOL_POSITIONS = {
103
106
  };
104
107
  var DEFAULTS = {
105
108
  HOOK: ADDRESSES.HOOK_STATIC_FEE_V2,
106
- /** LP Locker with fee conversion (converts fees to ETH before distributing) */
109
+ /** LP Locker with fee conversion (converts fees to WETH before distributing) */
107
110
  LOCKER: ADDRESSES.LP_LOCKER_FEE_CONVERSION,
108
111
  TICK_SPACING: 200,
109
112
  TICK_IF_TOKEN0_IS_LIQUID: -230400,
@@ -1143,6 +1146,73 @@ var LiquidSDK = class {
1143
1146
  extensionData
1144
1147
  };
1145
1148
  }
1149
+ // ── Airdrop Extension ──────────────────────────────────────────
1150
+ /**
1151
+ * Build an ExtensionConfig that reserves a percentage of supply into
1152
+ * the LiquidAirdropV2 contract for merkle-tree-based distribution.
1153
+ *
1154
+ * The airdrop contract expects `AirdropV2ExtensionData`:
1155
+ * { address admin, bytes32 merkleRoot, uint256 lockupDuration, uint256 vestingDuration }
1156
+ *
1157
+ * Leaf encoding used by LiquidAirdropV2.claim (note: **double hashed**
1158
+ * — OZ's standard 2nd-preimage-resistant pattern):
1159
+ * leaf = keccak256(bytes.concat(keccak256(abi.encode(recipient, allocatedAmount))))
1160
+ *
1161
+ * @example
1162
+ * ```typescript
1163
+ * const airdropExt = sdk.buildAirdropExtension({
1164
+ * admin: account.address,
1165
+ * merkleRoot: "0x…",
1166
+ * allocationBps: 2000, // 20%
1167
+ * lockupDuration: 86400, // 1 day (minimum)
1168
+ * vestingDuration: 0, // instant claim after lockup
1169
+ * });
1170
+ * ```
1171
+ */
1172
+ buildAirdropExtension(airdrop) {
1173
+ const MIN_LOCKUP = 86400;
1174
+ const MAX_BPS = 9e3;
1175
+ if (airdrop.allocationBps < 1 || airdrop.allocationBps > MAX_BPS) {
1176
+ throw new Error(
1177
+ `Airdrop allocationBps must be 1\u2013${MAX_BPS} (0.01%\u201390%). Got ${airdrop.allocationBps}.`
1178
+ );
1179
+ }
1180
+ if (airdrop.lockupDuration < MIN_LOCKUP) {
1181
+ throw new Error(
1182
+ `Airdrop lockupDuration must be \u2265 ${MIN_LOCKUP} seconds (1 day). Got ${airdrop.lockupDuration}.`
1183
+ );
1184
+ }
1185
+ if (airdrop.vestingDuration !== void 0 && airdrop.vestingDuration < 0) {
1186
+ throw new Error("Airdrop vestingDuration cannot be negative.");
1187
+ }
1188
+ const extensionData = encodeAbiParameters2(
1189
+ [
1190
+ {
1191
+ type: "tuple",
1192
+ components: [
1193
+ { type: "address", name: "admin" },
1194
+ { type: "bytes32", name: "merkleRoot" },
1195
+ { type: "uint256", name: "lockupDuration" },
1196
+ { type: "uint256", name: "vestingDuration" }
1197
+ ]
1198
+ }
1199
+ ],
1200
+ [
1201
+ {
1202
+ admin: airdrop.admin,
1203
+ merkleRoot: airdrop.merkleRoot,
1204
+ lockupDuration: BigInt(airdrop.lockupDuration),
1205
+ vestingDuration: BigInt(airdrop.vestingDuration ?? 0)
1206
+ }
1207
+ ]
1208
+ );
1209
+ return {
1210
+ extension: ADDRESSES.AIRDROP_V2,
1211
+ msgValue: 0n,
1212
+ extensionBps: airdrop.allocationBps,
1213
+ extensionData
1214
+ };
1215
+ }
1146
1216
  // ── Validation ─────────────────────────────────────────────────
1147
1217
  /**
1148
1218
  * Validate a DeploymentConfig before sending to the contract.
@@ -1307,13 +1377,36 @@ var LiquidSDK = class {
1307
1377
  (sum, ext) => sum + ext.msgValue,
1308
1378
  0n
1309
1379
  );
1380
+ let gas;
1381
+ try {
1382
+ const estimated = await this.publicClient.estimateContractGas({
1383
+ address: ADDRESSES.FACTORY,
1384
+ abi: LiquidFactoryAbi,
1385
+ functionName: "deployToken",
1386
+ args: [deploymentConfig],
1387
+ value: msgValue,
1388
+ account: this.walletClient.account
1389
+ });
1390
+ gas = estimated * 120n / 100n;
1391
+ } catch (err) {
1392
+ const e = err;
1393
+ const looksLikeRevert = e?.name === "ContractFunctionExecutionError" || e?.name === "CallExecutionError" || typeof e?.shortMessage === "string" && /reverted|revert reason|execution reverted/i.test(e.shortMessage);
1394
+ if (looksLikeRevert) throw err;
1395
+ if (typeof console !== "undefined" && console.warn) {
1396
+ console.warn(
1397
+ "[liquid-sdk] deployToken gas estimation failed; falling back to 6M gas limit:",
1398
+ e?.shortMessage ?? err
1399
+ );
1400
+ }
1401
+ gas = 6000000n;
1402
+ }
1310
1403
  const txHash = await this.walletClient.writeContract({
1311
1404
  address: ADDRESSES.FACTORY,
1312
1405
  abi: LiquidFactoryAbi,
1313
1406
  functionName: "deployToken",
1314
1407
  args: [deploymentConfig],
1315
1408
  value: msgValue,
1316
- gas: 5000000n,
1409
+ gas,
1317
1410
  chain: base2,
1318
1411
  account: this.walletClient.account
1319
1412
  });
@@ -2298,6 +2391,33 @@ function createDefaultPositions(startingMarketCapUSD, ethPriceUSD, tickSpacing =
2298
2391
  tickIfToken0IsLiquid: positions.tickLower[0]
2299
2392
  };
2300
2393
  }
2394
+ function shiftPositions(positions, shiftBy) {
2395
+ return positions.map((p) => ({
2396
+ tickLower: p.tickLower + shiftBy,
2397
+ tickUpper: p.tickUpper + shiftBy,
2398
+ positionBps: p.positionBps
2399
+ }));
2400
+ }
2401
+ function createLiquidPositionsUSD(startingMarketCapUSD, pairedTokenPriceUSD, tickSpacing = 200) {
2402
+ if (pairedTokenPriceUSD <= 0) {
2403
+ throw new Error("pairedTokenPriceUSD must be positive");
2404
+ }
2405
+ const startingTick = getTickFromMarketCapUSD(
2406
+ startingMarketCapUSD,
2407
+ pairedTokenPriceUSD,
2408
+ tickSpacing
2409
+ );
2410
+ const shifted = shiftPositions(
2411
+ POOL_POSITIONS.Liquid,
2412
+ startingTick - DEFAULTS.TICK_IF_TOKEN0_IS_LIQUID
2413
+ );
2414
+ return {
2415
+ tickLower: shifted.map((p) => p.tickLower),
2416
+ tickUpper: shifted.map((p) => p.tickUpper),
2417
+ positionBps: shifted.map((p) => p.positionBps),
2418
+ tickIfToken0IsLiquid: startingTick
2419
+ };
2420
+ }
2301
2421
  function describePositions(positions, ethPriceUSD) {
2302
2422
  return positions.tickLower.map((_, i) => {
2303
2423
  const lowerETH = Math.pow(1.0001, positions.tickLower[i]) * 1e11;
@@ -2346,6 +2466,7 @@ export {
2346
2466
  buildContext,
2347
2467
  buildMetadata,
2348
2468
  createDefaultPositions,
2469
+ createLiquidPositionsUSD,
2349
2470
  createPositions,
2350
2471
  createPositionsUSD,
2351
2472
  describePositions,
@@ -2359,6 +2480,7 @@ export {
2359
2480
  marketCapFromTickETH,
2360
2481
  marketCapFromTickUSD,
2361
2482
  parseContext,
2362
- parseMetadata
2483
+ parseMetadata,
2484
+ shiftPositions
2363
2485
  };
2364
2486
  //# sourceMappingURL=index.mjs.map