@cloakely/sdk 0.2.6 → 0.3.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/dist/cloak.d.ts CHANGED
@@ -91,11 +91,12 @@ export declare class Cloak {
91
91
  readonly publicClient: PublicClient;
92
92
  readonly walletClient?: Wallet | undefined;
93
93
  readonly factory?: Address | undefined;
94
- /** The first deployment's factory, so its launches still list and settle. */
95
- readonly legacyFactory?: Address | undefined;
94
+ /** Earlier deployments' factories (newest first), so their launches still list and settle. */
95
+ readonly legacyFactory?: (Address | readonly Address[]) | undefined;
96
96
  constructor(publicClient: PublicClient, walletClient?: Wallet | undefined, factory?: Address | undefined,
97
- /** The first deployment's factory, so its launches still list and settle. */
98
- legacyFactory?: Address | undefined);
97
+ /** Earlier deployments' factories (newest first), so their launches still list and settle. */
98
+ legacyFactory?: (Address | readonly Address[]) | undefined);
99
+ private get legacyFactories();
99
100
  private wallet;
100
101
  private send;
101
102
  createLaunch(p: LaunchParams): Promise<{
@@ -105,8 +106,8 @@ export declare class Cloak {
105
106
  block: bigint;
106
107
  }>;
107
108
  /**
108
- * Every launch, newest factory first. Launches from `legacyFactory` (the first deployment) are included with
109
- * `legacy: true`; they have no vesting contract.
109
+ * Every launch, newest factory first. Launches from the `legacyFactory` list (earlier deployments) are included with
110
+ * `legacy: true`; the first deployment's have no vesting contract.
110
111
  */
111
112
  listLaunches(): Promise<{
112
113
  auction: Address;
@@ -115,6 +116,7 @@ export declare class Cloak {
115
116
  launchpad: Address;
116
117
  creatorAlloc: bigint;
117
118
  vesting: Address;
119
+ factory: Address;
118
120
  legacy?: boolean;
119
121
  }[]>;
120
122
  private listLegacy;
@@ -722,6 +724,20 @@ export declare class Cloak {
722
724
  readonly internalType: "uint256";
723
725
  }];
724
726
  readonly stateMutability: "view";
727
+ }, {
728
+ readonly type: "function";
729
+ readonly name: "refundOwed";
730
+ readonly inputs: readonly [{
731
+ readonly name: "";
732
+ readonly type: "address";
733
+ readonly internalType: "address";
734
+ }];
735
+ readonly outputs: readonly [{
736
+ readonly name: "";
737
+ readonly type: "uint256";
738
+ readonly internalType: "uint256";
739
+ }];
740
+ readonly stateMutability: "view";
725
741
  }, {
726
742
  readonly type: "function";
727
743
  readonly name: "releaseLP";
@@ -859,6 +875,16 @@ export declare class Cloak {
859
875
  readonly inputs: readonly [];
860
876
  readonly outputs: readonly [];
861
877
  readonly stateMutability: "nonpayable";
878
+ }, {
879
+ readonly type: "function";
880
+ readonly name: "withdrawRefund";
881
+ readonly inputs: readonly [{
882
+ readonly name: "to";
883
+ readonly type: "address";
884
+ readonly internalType: "address";
885
+ }];
886
+ readonly outputs: readonly [];
887
+ readonly stateMutability: "nonpayable";
862
888
  }, {
863
889
  readonly type: "event";
864
890
  readonly name: "Claimed";
@@ -1039,6 +1065,41 @@ export declare class Cloak {
1039
1065
  readonly internalType: "uint256";
1040
1066
  }];
1041
1067
  readonly anonymous: false;
1068
+ }, {
1069
+ readonly type: "event";
1070
+ readonly name: "RefundHeld";
1071
+ readonly inputs: readonly [{
1072
+ readonly name: "bidder";
1073
+ readonly type: "address";
1074
+ readonly indexed: true;
1075
+ readonly internalType: "address";
1076
+ }, {
1077
+ readonly name: "amount";
1078
+ readonly type: "uint256";
1079
+ readonly indexed: false;
1080
+ readonly internalType: "uint256";
1081
+ }];
1082
+ readonly anonymous: false;
1083
+ }, {
1084
+ readonly type: "event";
1085
+ readonly name: "RefundWithdrawn";
1086
+ readonly inputs: readonly [{
1087
+ readonly name: "bidder";
1088
+ readonly type: "address";
1089
+ readonly indexed: true;
1090
+ readonly internalType: "address";
1091
+ }, {
1092
+ readonly name: "to";
1093
+ readonly type: "address";
1094
+ readonly indexed: false;
1095
+ readonly internalType: "address";
1096
+ }, {
1097
+ readonly name: "amount";
1098
+ readonly type: "uint256";
1099
+ readonly indexed: false;
1100
+ readonly internalType: "uint256";
1101
+ }];
1102
+ readonly anonymous: false;
1042
1103
  }, {
1043
1104
  readonly type: "event";
1044
1105
  readonly name: "Revealed";
package/dist/cloak.js CHANGED
@@ -62,13 +62,16 @@ export class Cloak {
62
62
  factory;
63
63
  legacyFactory;
64
64
  constructor(publicClient, walletClient, factory,
65
- /** The first deployment's factory, so its launches still list and settle. */
65
+ /** Earlier deployments' factories (newest first), so their launches still list and settle. */
66
66
  legacyFactory) {
67
67
  this.publicClient = publicClient;
68
68
  this.walletClient = walletClient;
69
69
  this.factory = factory;
70
70
  this.legacyFactory = legacyFactory;
71
71
  }
72
+ get legacyFactories() {
73
+ return this.legacyFactory === undefined ? [] : typeof this.legacyFactory === "string" ? [this.legacyFactory] : this.legacyFactory;
74
+ }
72
75
  wallet() {
73
76
  if (!this.walletClient)
74
77
  throw new Error("Cloak: a walletClient is required for this call");
@@ -111,26 +114,25 @@ export class Cloak {
111
114
  return { auction: ev.args.auction, token: ev.args.token, txHash, block: r.blockNumber };
112
115
  }
113
116
  /**
114
- * Every launch, newest factory first. Launches from `legacyFactory` (the first deployment) are included with
115
- * `legacy: true`; they have no vesting contract.
117
+ * Every launch, newest factory first. Launches from the `legacyFactory` list (earlier deployments) are included with
118
+ * `legacy: true`; the first deployment's have no vesting contract.
116
119
  */
117
120
  async listLaunches() {
118
121
  if (!this.factory)
119
122
  throw new Error("Cloak: factory address required");
120
- const legacy = this.legacyFactory ? await this.listLegacy(this.legacyFactory) : [];
123
+ const legacy = [];
124
+ for (const f of this.legacyFactories)
125
+ legacy.push(...(await this.listLegacy(f)));
121
126
  return [...(await this.listCurrent()), ...legacy];
122
127
  }
123
128
  async listLegacy(factory) {
124
129
  const n = await this.publicClient.readContract({ address: factory, abi: cloakFactoryAbi, functionName: "launchesCount" });
125
130
  const out = [];
126
131
  for (let i = 0n; i < n; i++) {
127
- const [auction, token, creator, launchpad, creatorAlloc] = await this.publicClient.readContract({
128
- address: factory,
129
- abi: LEGACY_LAUNCHES_ABI,
130
- functionName: "launches",
131
- args: [i],
132
- });
133
- out.push({ auction, token, creator, launchpad, creatorAlloc, vesting: zeroAddress, legacy: true });
132
+ // a factory from v2 on returns a vesting contract too; the first one returns five fields
133
+ const six = await this.publicClient.readContract({ address: factory, abi: cloakFactoryAbi, functionName: "launches", args: [i] }).catch(() => null);
134
+ const [auction, token, creator, launchpad, creatorAlloc] = six ?? (await this.publicClient.readContract({ address: factory, abi: LEGACY_LAUNCHES_ABI, functionName: "launches", args: [i] }));
135
+ out.push({ auction, token, creator, launchpad, creatorAlloc, vesting: (six?.[5] ?? zeroAddress), factory, legacy: true });
134
136
  }
135
137
  return out;
136
138
  }
@@ -150,7 +152,7 @@ export class Cloak {
150
152
  functionName: "launches",
151
153
  args: [i],
152
154
  });
153
- out.push({ auction, token, creator, launchpad, creatorAlloc, vesting });
155
+ out.push({ auction, token, creator, launchpad, creatorAlloc, vesting, factory: this.factory });
154
156
  }
155
157
  return out;
156
158
  }
@@ -1,13 +1,28 @@
1
1
  import type { Address } from "viem";
2
+ /** An earlier deployment on the same chain: its launches still list, and `migrator` moves its private balances here. */
3
+ export interface PreviousDeployment {
4
+ version: number;
5
+ factory: Address;
6
+ router: Address;
7
+ routerBlock: bigint;
8
+ batcher?: Address;
9
+ /** Moves this deployment's private balances into the current one (`CloakPrivate.migrateFrom(…, { migrator })`). */
10
+ migrator?: Address;
11
+ }
2
12
  /** Where Cloak lives on each chain, so integrators never copy addresses by hand. */
3
13
  export interface CloakDeployment {
4
14
  chainId: number;
15
+ /** Which Cloak deployment this is (3 on Elysium testnet). */
16
+ version: number;
5
17
  config: Address;
6
18
  factory: Address;
19
+ /** Block the factory was deployed in: scan launch events from here. */
20
+ factoryBlock: bigint;
7
21
  router: Address;
8
22
  /** Block the router was deployed in: scan private-pool events from here. */
9
23
  routerBlock: bigint;
10
24
  batcher: Address;
25
+ /** The migrator from the newest earlier deployment (each one in `previous` has its own). */
11
26
  migrator?: Address;
12
27
  hypePool: Address;
13
28
  whype: Address;
@@ -23,12 +38,8 @@ export interface CloakDeployment {
23
38
  decimals: number;
24
39
  fromBlock: bigint;
25
40
  }[];
26
- /** The first deployment: its launches still list, and its private balances move here through `migrator`. */
27
- legacy?: {
28
- factory: Address;
29
- router: Address;
30
- routerBlock: bigint;
31
- };
41
+ /** Earlier deployments, newest first. */
42
+ previous?: PreviousDeployment[];
32
43
  }
33
44
  export declare const deployments: Record<number, CloakDeployment>;
34
45
  /** The Cloak deployment on `chainId`, or an error naming the chains Cloak is on. */
@@ -1,13 +1,16 @@
1
1
  export const deployments = {
2
+ // Cloak v3 (Oct 30): deployments/elysium-testnet-v3.json
2
3
  99801: {
3
4
  chainId: 99801,
5
+ version: 3,
4
6
  config: "0x9d30c7b23fa2d5c40779d3db3bb4292e18c94373",
5
- factory: "0xc1fc14e84cbbd10f75dad9d91bf50f47c48757fc",
6
- router: "0xd51e731467c49991496329c2b7979cb1aa220ee2",
7
- routerBlock: 15856031n,
8
- batcher: "0xa13ffd763a8cccfea1b868c616291723579ddb77",
9
- migrator: "0xe54c02fa685f2c95e5ae98e1155547194d04d9ad",
10
- hypePool: "0x4deFEC0814d11c581e5947020ac4ec41e88B55Df",
7
+ factory: "0xd0f4aacf339f07211a9155194925b2f94e250e29",
8
+ factoryBlock: 19096456n,
9
+ router: "0x78319bee7c21ca411166acc67c750aca10280e86",
10
+ routerBlock: 19096485n,
11
+ batcher: "0x9902d86c5be81f6c6ce059acf4c89193d06069c4",
12
+ migrator: "0x295f816aa6dac1901bd793120248d8f9cbbd5eec",
13
+ hypePool: "0x786886a61Dd77581ef03787c5939fC44B004064d",
11
14
  whype: "0xe44b27113D4b947c0B1bDf4a93878D0e115f4bdD",
12
15
  relayerUrl: "https://cloak-keeper.onrender.com",
13
16
  circuitsUrl: "https://cloak.boblabs.tech/circuits",
@@ -15,11 +18,24 @@ export const deployments = {
15
18
  // Elysium testnet USDC (bridged from Circle's USDC on HyperEVM): private sends and withdrawals
16
19
  { symbol: "USDC", token: "0x7D29d8047B905000459c0E80c34a26CeedcB47b2", pool: "0x61de30970e3c53665ce5a89323284e7ab379fa08", decimals: 6, fromBlock: 18329466n },
17
20
  ],
18
- legacy: {
19
- factory: "0x1dc1ea9837ecbd31ec74f0d558e1db1c303a7e1c",
20
- router: "0xfa2574cfc3afb8f7d3a0651fa2111ff4e3d2fc41",
21
- routerBlock: 10973723n,
22
- },
21
+ previous: [
22
+ {
23
+ version: 2,
24
+ factory: "0xc1fc14e84cbbd10f75dad9d91bf50f47c48757fc",
25
+ router: "0xd51e731467c49991496329c2b7979cb1aa220ee2",
26
+ routerBlock: 15856031n,
27
+ batcher: "0xa13ffd763a8cccfea1b868c616291723579ddb77",
28
+ migrator: "0x295f816aa6dac1901bd793120248d8f9cbbd5eec",
29
+ },
30
+ {
31
+ version: 1,
32
+ factory: "0x1dc1ea9837ecbd31ec74f0d558e1db1c303a7e1c",
33
+ router: "0xfa2574cfc3afb8f7d3a0651fa2111ff4e3d2fc41",
34
+ routerBlock: 10973723n,
35
+ batcher: "0xf6582cc5a84fccf74e571e652fb7b603a2c25812",
36
+ migrator: "0x5f3d82a6aa1b20ba9d0f58a98d1c4933c115a0da",
37
+ },
38
+ ],
23
39
  },
24
40
  };
25
41
  /** The Cloak deployment on `chainId`, or an error naming the chains Cloak is on. */
@@ -11,6 +11,8 @@ export interface RelayCall {
11
11
  pool: Address;
12
12
  proof: ProofArgs;
13
13
  extData: ExtData;
14
+ /** For `migrate`: the migrator from the pool's deployment into this one (the proof pays out to it). */
15
+ migrator?: Address;
14
16
  }
15
17
  /** What a relayer charges for one call, paid out of the pool's own token inside the proof. */
16
18
  export interface RelayQuote {
@@ -173,9 +175,12 @@ export declare class CloakPrivate {
173
175
  /**
174
176
  * Move every private balance `legacy` (a client on the earlier router, with the earlier keys) can see into this
175
177
  * deployment, note by note, through `CloakMigrator`. Each move is one relayed transaction: the old proof withdraws to
176
- * the migrator, which deposits the same amount here as a new note for one of this account's one-time keys.
178
+ * the migrator, which deposits the same amount here as a new note for one of this account's one-time keys. Each
179
+ * earlier deployment has its own migrator into this one: pass it as `opts.migrator` (default: `this.migrator`).
177
180
  */
178
- migrateFrom(legacy: CloakPrivate, onStatus?: Status): Promise<{
181
+ migrateFrom(legacy: CloakPrivate, onStatus?: Status, opts?: {
182
+ migrator?: Address;
183
+ }): Promise<{
179
184
  token: Address;
180
185
  amount: bigint;
181
186
  txHash: Hex;
@@ -36,10 +36,11 @@ export function relayerSubmitter(url) {
36
36
  export function walletSubmitter(publicClient, wallet, router, batcher, migrator) {
37
37
  return async (call) => {
38
38
  // viem cannot infer the nested tuple types through the union; the shapes match the ABI exactly.
39
- if (call.kind === "migrate" && !migrator)
39
+ const mig = call.migrator ?? migrator;
40
+ if (call.kind === "migrate" && !mig)
40
41
  throw new Error("no migrator configured");
41
42
  const req = call.kind === "migrate"
42
- ? { address: migrator, abi: cloakMigratorAbi, functionName: "migrate", args: [call.pool, call.proof, call.extData] }
43
+ ? { address: mig, abi: cloakMigratorAbi, functionName: "migrate", args: [call.pool, call.proof, call.extData] }
43
44
  : call.kind === "placeOrder"
44
45
  ? { address: batcher, abi: privateBatcherAbi, functionName: "placeOrder", args: [call.pool, call.proof, call.extData] }
45
46
  : call.kind === "privateSwap"
@@ -562,9 +563,11 @@ export class CloakPrivate {
562
563
  /**
563
564
  * Move every private balance `legacy` (a client on the earlier router, with the earlier keys) can see into this
564
565
  * deployment, note by note, through `CloakMigrator`. Each move is one relayed transaction: the old proof withdraws to
565
- * the migrator, which deposits the same amount here as a new note for one of this account's one-time keys.
566
+ * the migrator, which deposits the same amount here as a new note for one of this account's one-time keys. Each
567
+ * earlier deployment has its own migrator into this one: pass it as `opts.migrator` (default: `this.migrator`).
566
568
  */
567
- async migrateFrom(legacy, onStatus = () => { }) {
569
+ async migrateFrom(legacy, onStatus = () => { }, opts = {}) {
570
+ const migrator = opts.migrator ?? this.migratorAddress();
568
571
  const moved = [];
569
572
  const markets = await legacy.loadMarkets();
570
573
  await this.loadMarkets();
@@ -577,7 +580,7 @@ export class CloakPrivate {
577
580
  break;
578
581
  const inputs = live.slice(0, 2);
579
582
  const total = inputs.reduce((a, x) => a + x.amount, 0n);
580
- const q = await legacy.relayFee("migrate", m.pool);
583
+ const q = await this.relayFee("migrate", m.pool); // quoted by the relayer that will submit it
581
584
  if (total <= q.fee)
582
585
  break; // dust that costs more to move than it's worth
583
586
  const amount = total - q.fee;
@@ -595,13 +598,13 @@ export class CloakPrivate {
595
598
  extAmount: -amount,
596
599
  fee: q.fee,
597
600
  relayer: q.relayer,
598
- recipient: this.migratorAddress(),
601
+ recipient: migrator,
599
602
  data,
600
603
  ...(await legacy.dummy()),
601
604
  prover: await this.prover(),
602
605
  });
603
606
  onStatus(`Moving ${m.symbol ?? "balance"}: relaying…`);
604
- const txHash = await this.submit({ kind: "migrate", pool: m.pool, proof, extData });
607
+ const txHash = await this.submit({ kind: "migrate", pool: m.pool, proof, extData, migrator });
605
608
  await this.publicClient.waitForTransactionReceipt({ hash: txHash });
606
609
  moved.push({ token: m.token, amount, txHash });
607
610
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloakely/sdk",
3
- "version": "0.2.6",
3
+ "version": "0.3.0",
4
4
  "description": "Cloak on Elysium: sealed-bid token launches and private trading (shielded balances, private swaps, batch auctions, private sends) with on-device zero-knowledge proofs.",
5
5
  "keywords": [
6
6
  "cloak",