@cloakely/sdk 0.8.1 → 0.8.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/cloak.d.ts CHANGED
@@ -60,8 +60,12 @@ export interface AuctionState {
60
60
  raised: bigint;
61
61
  /** The market Cloak trades: a CloakV2Market in front of a Uniswap V2 pool, or (earlier launches) a CloakPair. */
62
62
  pair: Address;
63
- /** The launch's Uniswap V2 pool (token / WHYPE), tradable and tracked everywhere. Zero for a CloakPair market. */
63
+ /** The launch's Uniswap pool: a V2 pool (token / WHYPE), or for a v4 launch its CloakV4Market. Zero for a CloakPair. */
64
64
  uniPair: Address;
65
+ /** Which market the launch opens: a Uniswap v4 pool with Cloak's hook, a Uniswap V2 pool, or (earlier launches) a CloakPair. */
66
+ pool: "v4" | "v2" | "cloak";
67
+ /** For a v4 launch: the hook that seeds and looks after its pool. */
68
+ hook?: Address;
65
69
  /** The LP is locked forever and the creator earns its trading fees (see `creatorFees`). */
66
70
  creatorFees: boolean;
67
71
  tokenName: string;
@@ -115,6 +119,8 @@ export declare class Cloak {
115
119
  txHash: Hex;
116
120
  block: bigint;
117
121
  }>;
122
+ /** Whether this factory's launches may lock LP until a date (false for Uniswap v4 launches). */
123
+ timedLocks(): Promise<boolean>;
118
124
  /**
119
125
  * Every launch, newest factory first. Launches from the `legacyFactory` list (earlier deployments) are included with
120
126
  * `legacy: true`; the first deployment's have no vesting contract.
package/dist/cloak.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { zeroAddress, encodeAbiParameters, keccak256, parseEventLogs, toHex, } from "viem";
2
- import { cloakAuctionAbi, cloakFactoryAbi, cloakFeeLockerAbi, cloakPairAbi, cloakTokenAbi } from "./abis.js";
2
+ import { cloakAuctionAbi, cloakFactoryAbi, cloakFeeLockerAbi, cloakPairAbi, cloakTokenAbi, cloakV4HookAbi } from "./abis.js";
3
3
  /** `lpLockUntil` for "locked forever, the creator earns the pool's trading fees". */
4
4
  export const LOCK_FOREVER_FEES = 2n ** 64n - 1n;
5
5
  import { drandRoundAt, sealBid, unsealBid } from "./seal.js";
@@ -91,6 +91,8 @@ export class Cloak {
91
91
  throw new Error("Cloak: factory address required");
92
92
  const w = this.wallet();
93
93
  const lock = p.lpLockUntil === undefined || p.lpLockUntil === "burn" ? 0n : p.lpLockUntil === "fees" ? LOCK_FOREVER_FEES : BigInt(p.lpLockUntil);
94
+ if (lock !== 0n && lock !== LOCK_FOREVER_FEES && !(await this.timedLocks()))
95
+ throw new Error("Launches from this factory open a Uniswap v4 pool, whose liquidity stays locked: choose \"burn\" or \"fees\" (locked forever, trading fees to the creator), not a lock date.");
94
96
  const params = {
95
97
  creator: p.creator ?? w.account.address,
96
98
  saleSupply: p.saleSupply,
@@ -115,6 +117,12 @@ export class Cloak {
115
117
  const [ev] = parseEventLogs({ abi: cloakFactoryAbi, logs: r.logs, eventName: "LaunchCreated" });
116
118
  return { auction: ev.args.auction, token: ev.args.token, txHash, block: r.blockNumber };
117
119
  }
120
+ /** Whether this factory's launches may lock LP until a date (false for Uniswap v4 launches). */
121
+ async timedLocks() {
122
+ if (!this.factory)
123
+ return true;
124
+ return this.publicClient.readContract({ address: this.factory, abi: cloakFactoryAbi, functionName: "timedLocks" }).catch(() => true);
125
+ }
118
126
  /**
119
127
  * Every launch, newest factory first. Launches from the `legacyFactory` list (earlier deployments) are included with
120
128
  * `legacy: true`; the first deployment's have no vesting contract.
@@ -174,6 +182,9 @@ export class Cloak {
174
182
  r.readContract({ ...c, functionName: "uniPair" }).catch(() => zeroAddress),
175
183
  r.readContract({ ...c, functionName: "creatorFees" }).catch(() => false),
176
184
  ]);
185
+ // a v4 launch's seeder is CloakV4Hook, the only seeder that says it can't hand LP back after a timed lock
186
+ const seeder = await r.readContract({ ...c, functionName: "seeder" }).catch(() => zeroAddress);
187
+ const v4 = seeder !== zeroAddress && (await r.readContract({ address: seeder, abi: cloakV4HookAbi, functionName: "timedLocks" }).then((t) => t === false, () => false));
177
188
  const [creator, saleSupply, lpReserve, minPrice, tickSize, numTicks, commitEnd, revealEnd, lpBps, noRevealPenaltyBps, lpLockUntil, tlockRound] = params;
178
189
  const [tokenName, tokenSymbol] = await Promise.all([
179
190
  r.readContract({ address: token, abi: cloakTokenAbi, functionName: "name" }),
@@ -207,7 +218,10 @@ export class Cloak {
207
218
  raised,
208
219
  pair,
209
220
  uniPair,
210
- creatorFees,
221
+ pool: v4 ? "v4" : uniPair !== zeroAddress ? "v2" : "cloak",
222
+ ...(v4 ? { hook: seeder } : {}),
223
+ // a v4 launch "locked forever" pays its creator through the hook rather than the V2 fee locker
224
+ creatorFees: creatorFees || (v4 && BigInt(lpLockUntil) === LOCK_FOREVER_FEES),
211
225
  tokenName,
212
226
  tokenSymbol,
213
227
  launchFeeBps,
@@ -223,6 +237,18 @@ export class Cloak {
223
237
  */
224
238
  async creatorFees(auction) {
225
239
  const c = { address: auction, abi: cloakAuctionAbi };
240
+ const s = await this.getAuction(auction);
241
+ if (s.pool === "v4") {
242
+ if (!s.creatorFees || !s.hook || s.uniPair === zeroAddress)
243
+ return null;
244
+ // what collectFees would pay right now, without sending anything
245
+ const [{ result }, launch] = await Promise.all([
246
+ this.publicClient.simulateContract({ address: s.hook, abi: cloakV4HookAbi, functionName: "collectFees", args: [s.token] }),
247
+ this.publicClient.readContract({ address: s.hook, abi: cloakV4HookAbi, functionName: "launchOf", args: [s.token] }),
248
+ ]);
249
+ const [h, t] = result;
250
+ return { locker: s.hook, position: 0n, beneficiary: launch.feeTo, claimableLp: h + t > 0n ? 1n : 0n, tokens: t, whype: h };
251
+ }
226
252
  const on = await this.publicClient.readContract({ ...c, functionName: "creatorFees" }).catch(() => false);
227
253
  if (!on)
228
254
  return null;
@@ -249,6 +275,9 @@ export class Cloak {
249
275
  throw new Error("this launch has no creator fees");
250
276
  if (f.claimableLp === 0n)
251
277
  throw new Error("no fees earned yet");
278
+ const s = await this.getAuction(auction);
279
+ if (s.pool === "v4")
280
+ return this.send(await this.wallet().writeContract({ address: f.locker, abi: cloakV4HookAbi, functionName: "collectFees", args: [s.token] })).then((r) => r.transactionHash);
252
281
  return this.send(await this.wallet().writeContract({ address: f.locker, abi: cloakFeeLockerAbi, functionName: "claim", args: [f.position] })).then((r) => r.transactionHash);
253
282
  }
254
283
  /** Revealed demand per tick (empty until the reveal phase — that is the point). */
@@ -34,6 +34,10 @@ export interface CloakDeployment {
34
34
  firstFactoryBlock?: bigint;
35
35
  /** CloakSeeder: opens each settled launch's market (a Uniswap V2 pool where the chain has one). */
36
36
  seeder?: Address;
37
+ /** Uniswap v4's PoolManager (on testnet, Cloak's deployment of Uniswap's exact build; on mainnet, Uniswap's own). */
38
+ poolManager?: Address;
39
+ /** CloakV4Hook: seeds and looks after every v4 launch's pool. */
40
+ v4Hook?: Address;
37
41
  /** CloakFeeLocker: holds "locked forever" LP and pays its trading fees to the creator. */
38
42
  feeLocker?: Address;
39
43
  router: Address;
@@ -50,6 +54,12 @@ export interface CloakDeployment {
50
54
  sharedRouter?: Address;
51
55
  /** SharedBatcher: batch rounds for the shared vault's tokens. */
52
56
  sharedBatcher?: Address;
57
+ /** CloakDropFactory: sealed NFT drops. */
58
+ dropFactory?: Address;
59
+ /** Block the drop factory was deployed in: scan drop events from here. */
60
+ dropFactoryBlock?: bigint;
61
+ /** CloakSpotBook: WL spot sales on top of drops; winners name the wallets to whitelist. */
62
+ spotBook?: Address;
53
63
  hypePool: Address;
54
64
  whype: Address;
55
65
  /** Hosted relayer (POST /relay, GET /quote). */
@@ -9,19 +9,27 @@ export const deployments = {
9
9
  config: "0x9fdf166f0671166148ea98cdd3ef0118d256167f",
10
10
  vaults: "0x24bc1d369aab3a2d741a48f8cac1af5dfd9f3d43",
11
11
  vaultsBlock: 19485039n,
12
- // the creator-fee launch factory (Nov 2): every launch opens a Uniswap V2 pool at its clearing price, and its LP can
13
- // be locked forever with the trading fees going to the creator
14
- factory: "0xd179bad69715f4bd4796dd7a4103be143fba02ad",
15
- factoryBlock: 21312271n,
16
- earlierFactories: ["0xeac84944f5a8343edf49cde8ef74d71f4908a656", "0xa88df63d7d44acc66052e5cbe5ba9503bf940993"],
12
+ // the Uniswap v4 launch factory (Nov 3): every launch opens a v4 pool (native HYPE / token) at its clearing price
13
+ // through CloakV4Hook, which keeps the liquidity forever, pays trading fees to the creator and charges an anti-snipe
14
+ // fee for 5 minutes after listing. The PoolManager is Uniswap's, built byte for byte like mainnet's.
15
+ factory: "0x1b0072684e98d9e23018e2d107ed8166ef84c077",
16
+ factoryBlock: 22661576n,
17
+ // the creator-fee V2 factory (Nov 2), then v4's first two
18
+ earlierFactories: ["0xd179bad69715f4bd4796dd7a4103be143fba02ad", "0xeac84944f5a8343edf49cde8ef74d71f4908a656", "0xa88df63d7d44acc66052e5cbe5ba9503bf940993"],
17
19
  firstFactoryBlock: 19484794n,
18
- seeder: "0x633aa82b806dafc0ae4c84418d23f3726139a88d",
20
+ seeder: "0xcdc11340c5ce0b3dcbd9a5e8f7838e8a8bbaaa80",
21
+ poolManager: "0x51027076df8416e42ea8438b27a0c433d9662e68",
22
+ v4Hook: "0xcdc11340c5ce0b3dcbd9a5e8f7838e8a8bbaaa80",
19
23
  feeLocker: "0x3b74062a72b16f9a221d63515518a635414501d8",
20
24
  // the shared launch-token vault (Nov 2, testnet experiment): new Uniswap launches keep their private balances here
21
25
  shared: "0x0ce2ecb0195e07899377e3d7b01e927ab3f87610",
22
26
  sharedBlock: 21426599n,
23
27
  sharedRouter: "0xe2a0769a5acbd987c1b6725247c56187a112dc7e",
24
28
  sharedBatcher: "0xdc725bdeb0fca923bf2dc65232f54463b0f80820",
29
+ // sealed NFT drops (Nov 3): GTD, then a sealed auction with the creator's price as the floor and a WL bid boost
30
+ dropFactory: "0x2afb7d9a5baa02a2d72a7c761521fc66dce9d783",
31
+ dropFactoryBlock: 22329730n,
32
+ spotBook: "0x91806d96814cc205d4b642e280023a1c7b361fc8",
25
33
  router: "0x343ab9a7aac93cee28321410510ea24417cc6386",
26
34
  routerBlock: 19485063n,
27
35
  batcher: "0xc69e4bca18020ae93bc9f17093985bfb139a3203",