@cloakely/sdk 0.3.1 → 0.5.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/abis.d.ts +1037 -172
- package/dist/abis.js +1421 -294
- package/dist/bytecode.d.ts +10 -7
- package/dist/bytecode.js +1 -1
- package/dist/cloak.d.ts +83 -0
- package/dist/cloak.js +18 -28
- package/dist/deployments.d.ts +26 -5
- package/dist/deployments.js +79 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/private/client.d.ts +28 -4
- package/dist/private/client.js +84 -20
- package/dist/private/crypto.d.ts +23 -5
- package/dist/private/crypto.js +14 -5
- package/dist/registry.d.ts +48 -0
- package/dist/registry.js +54 -0
- package/package.json +1 -1
package/dist/cloak.d.ts
CHANGED
|
@@ -53,7 +53,10 @@ export interface AuctionState {
|
|
|
53
53
|
clearingPrice: bigint;
|
|
54
54
|
sold: bigint;
|
|
55
55
|
raised: bigint;
|
|
56
|
+
/** The market Cloak trades: a CloakV2Market in front of a Uniswap V2 pool, or (earlier launches) a CloakPair. */
|
|
56
57
|
pair: Address;
|
|
58
|
+
/** The launch's Uniswap V2 pool (token / WHYPE), tradable and tracked everywhere. Zero for a CloakPair market. */
|
|
59
|
+
uniPair: Address;
|
|
57
60
|
tokenName: string;
|
|
58
61
|
tokenSymbol: string;
|
|
59
62
|
/** Launch fee on a successful raise, fixed when the auction was created. */
|
|
@@ -117,6 +120,7 @@ export declare class Cloak {
|
|
|
117
120
|
creatorAlloc: bigint;
|
|
118
121
|
vesting: Address;
|
|
119
122
|
factory: Address;
|
|
123
|
+
index: bigint;
|
|
120
124
|
legacy?: boolean;
|
|
121
125
|
}[]>;
|
|
122
126
|
private listLegacy;
|
|
@@ -217,8 +221,15 @@ export declare class Cloak {
|
|
|
217
221
|
readonly name: "config_";
|
|
218
222
|
readonly type: "address";
|
|
219
223
|
readonly internalType: "contract CloakConfig";
|
|
224
|
+
}, {
|
|
225
|
+
readonly name: "seeder_";
|
|
226
|
+
readonly type: "address";
|
|
227
|
+
readonly internalType: "contract IMarketSeeder";
|
|
220
228
|
}];
|
|
221
229
|
readonly stateMutability: "nonpayable";
|
|
230
|
+
}, {
|
|
231
|
+
readonly type: "receive";
|
|
232
|
+
readonly stateMutability: "payable";
|
|
222
233
|
}, {
|
|
223
234
|
readonly type: "function";
|
|
224
235
|
readonly name: "DEAD";
|
|
@@ -341,6 +352,28 @@ export declare class Cloak {
|
|
|
341
352
|
}];
|
|
342
353
|
readonly outputs: readonly [];
|
|
343
354
|
readonly stateMutability: "nonpayable";
|
|
355
|
+
}, {
|
|
356
|
+
readonly type: "function";
|
|
357
|
+
readonly name: "claimPrivate";
|
|
358
|
+
readonly inputs: readonly [{
|
|
359
|
+
readonly name: "id";
|
|
360
|
+
readonly type: "uint256";
|
|
361
|
+
readonly internalType: "uint256";
|
|
362
|
+
}, {
|
|
363
|
+
readonly name: "pubKey";
|
|
364
|
+
readonly type: "uint256";
|
|
365
|
+
readonly internalType: "uint256";
|
|
366
|
+
}, {
|
|
367
|
+
readonly name: "blinding";
|
|
368
|
+
readonly type: "uint256";
|
|
369
|
+
readonly internalType: "uint256";
|
|
370
|
+
}, {
|
|
371
|
+
readonly name: "memo";
|
|
372
|
+
readonly type: "bytes";
|
|
373
|
+
readonly internalType: "bytes";
|
|
374
|
+
}];
|
|
375
|
+
readonly outputs: readonly [];
|
|
376
|
+
readonly stateMutability: "nonpayable";
|
|
344
377
|
}, {
|
|
345
378
|
readonly type: "function";
|
|
346
379
|
readonly name: "claimedCount";
|
|
@@ -807,6 +840,16 @@ export declare class Cloak {
|
|
|
807
840
|
readonly internalType: "uint256";
|
|
808
841
|
}];
|
|
809
842
|
readonly stateMutability: "view";
|
|
843
|
+
}, {
|
|
844
|
+
readonly type: "function";
|
|
845
|
+
readonly name: "seeder";
|
|
846
|
+
readonly inputs: readonly [];
|
|
847
|
+
readonly outputs: readonly [{
|
|
848
|
+
readonly name: "";
|
|
849
|
+
readonly type: "address";
|
|
850
|
+
readonly internalType: "contract IMarketSeeder";
|
|
851
|
+
}];
|
|
852
|
+
readonly stateMutability: "view";
|
|
810
853
|
}, {
|
|
811
854
|
readonly type: "function";
|
|
812
855
|
readonly name: "settle";
|
|
@@ -869,6 +912,16 @@ export declare class Cloak {
|
|
|
869
912
|
readonly internalType: "uint256";
|
|
870
913
|
}];
|
|
871
914
|
readonly stateMutability: "view";
|
|
915
|
+
}, {
|
|
916
|
+
readonly type: "function";
|
|
917
|
+
readonly name: "uniPair";
|
|
918
|
+
readonly inputs: readonly [];
|
|
919
|
+
readonly outputs: readonly [{
|
|
920
|
+
readonly name: "";
|
|
921
|
+
readonly type: "address";
|
|
922
|
+
readonly internalType: "address";
|
|
923
|
+
}];
|
|
924
|
+
readonly stateMutability: "view";
|
|
872
925
|
}, {
|
|
873
926
|
readonly type: "function";
|
|
874
927
|
readonly name: "withdrawProceeds";
|
|
@@ -915,6 +968,16 @@ export declare class Cloak {
|
|
|
915
968
|
readonly internalType: "uint256";
|
|
916
969
|
}];
|
|
917
970
|
readonly anonymous: false;
|
|
971
|
+
}, {
|
|
972
|
+
readonly type: "event";
|
|
973
|
+
readonly name: "ClaimedPrivately";
|
|
974
|
+
readonly inputs: readonly [{
|
|
975
|
+
readonly name: "id";
|
|
976
|
+
readonly type: "uint256";
|
|
977
|
+
readonly indexed: true;
|
|
978
|
+
readonly internalType: "uint256";
|
|
979
|
+
}];
|
|
980
|
+
readonly anonymous: false;
|
|
918
981
|
}, {
|
|
919
982
|
readonly type: "event";
|
|
920
983
|
readonly name: "Committed";
|
|
@@ -1150,6 +1213,26 @@ export declare class Cloak {
|
|
|
1150
1213
|
readonly internalType: "uint256";
|
|
1151
1214
|
}];
|
|
1152
1215
|
readonly anonymous: false;
|
|
1216
|
+
}, {
|
|
1217
|
+
readonly type: "event";
|
|
1218
|
+
readonly name: "UniswapMarket";
|
|
1219
|
+
readonly inputs: readonly [{
|
|
1220
|
+
readonly name: "uniPair";
|
|
1221
|
+
readonly type: "address";
|
|
1222
|
+
readonly indexed: true;
|
|
1223
|
+
readonly internalType: "address";
|
|
1224
|
+
}, {
|
|
1225
|
+
readonly name: "market";
|
|
1226
|
+
readonly type: "address";
|
|
1227
|
+
readonly indexed: false;
|
|
1228
|
+
readonly internalType: "address";
|
|
1229
|
+
}, {
|
|
1230
|
+
readonly name: "lpShares";
|
|
1231
|
+
readonly type: "uint256";
|
|
1232
|
+
readonly indexed: false;
|
|
1233
|
+
readonly internalType: "uint256";
|
|
1234
|
+
}];
|
|
1235
|
+
readonly anonymous: false;
|
|
1153
1236
|
}], "Committed", true, bigint, bigint>>;
|
|
1154
1237
|
/**
|
|
1155
1238
|
* Decrypt every sealed bid whose drand round has passed and reveal them in batches. Anyone can run this — it needs no
|
package/dist/cloak.js
CHANGED
|
@@ -120,47 +120,34 @@ export class Cloak {
|
|
|
120
120
|
async listLaunches() {
|
|
121
121
|
if (!this.factory)
|
|
122
122
|
throw new Error("Cloak: factory address required");
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return [...(await this.listCurrent()), ...legacy];
|
|
123
|
+
// every factory, and every launch in it, read at once (a multicall client folds them into a few requests)
|
|
124
|
+
const [current, ...legacy] = await Promise.all([this.listCurrent(), ...this.legacyFactories.map((f) => this.listLegacy(f))]);
|
|
125
|
+
return [...current, ...legacy.flat()];
|
|
127
126
|
}
|
|
128
127
|
async listLegacy(factory) {
|
|
129
128
|
const n = await this.publicClient.readContract({ address: factory, abi: cloakFactoryAbi, functionName: "launchesCount" });
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
return Promise.all(Array.from({ length: Number(n) }, async (_, k) => {
|
|
130
|
+
const i = BigInt(k);
|
|
132
131
|
// a factory from v2 on returns a vesting contract too; the first one returns five fields
|
|
133
132
|
const six = await this.publicClient.readContract({ address: factory, abi: cloakFactoryAbi, functionName: "launches", args: [i] }).catch(() => null);
|
|
134
133
|
const [auction, token, creator, launchpad, creatorAlloc] = six ?? (await this.publicClient.readContract({ address: factory, abi: LEGACY_LAUNCHES_ABI, functionName: "launches", args: [i] }));
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
return out;
|
|
134
|
+
return { auction, token, creator, launchpad, creatorAlloc, vesting: (six?.[5] ?? zeroAddress), factory, index: i, legacy: true };
|
|
135
|
+
}));
|
|
138
136
|
}
|
|
139
137
|
async listCurrent() {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
abi: cloakFactoryAbi,
|
|
145
|
-
|
|
146
|
-
});
|
|
147
|
-
const out = [];
|
|
148
|
-
for (let i = 0n; i < n; i++) {
|
|
149
|
-
const [auction, token, creator, launchpad, creatorAlloc, vesting] = await this.publicClient.readContract({
|
|
150
|
-
address: this.factory,
|
|
151
|
-
abi: cloakFactoryAbi,
|
|
152
|
-
functionName: "launches",
|
|
153
|
-
args: [i],
|
|
154
|
-
});
|
|
155
|
-
out.push({ auction, token, creator, launchpad, creatorAlloc, vesting, factory: this.factory });
|
|
156
|
-
}
|
|
157
|
-
return out;
|
|
138
|
+
const factory = this.factory;
|
|
139
|
+
const n = await this.publicClient.readContract({ address: factory, abi: cloakFactoryAbi, functionName: "launchesCount" });
|
|
140
|
+
return Promise.all(Array.from({ length: Number(n) }, async (_, k) => {
|
|
141
|
+
const index = BigInt(k);
|
|
142
|
+
const [auction, token, creator, launchpad, creatorAlloc, vesting] = await this.publicClient.readContract({ address: factory, abi: cloakFactoryAbi, functionName: "launches", args: [index] });
|
|
143
|
+
return { auction, token, creator, launchpad, creatorAlloc, vesting, factory, index };
|
|
144
|
+
}));
|
|
158
145
|
}
|
|
159
146
|
// ───────────── reads ─────────────
|
|
160
147
|
async getAuction(auction) {
|
|
161
148
|
const c = { address: auction, abi: cloakAuctionAbi };
|
|
162
149
|
const r = this.publicClient;
|
|
163
|
-
const [params, token, phase, commits, reveals, totalDeposits, totalDemand, settled, failed, clearingTick, clearingPrice, sold, raised, pair, launchFeeBps, bidCap, depositCap, creatorOwed, feesOwed] = await Promise.all([
|
|
150
|
+
const [params, token, phase, commits, reveals, totalDeposits, totalDemand, settled, failed, clearingTick, clearingPrice, sold, raised, pair, launchFeeBps, bidCap, depositCap, creatorOwed, feesOwed, uniPair] = await Promise.all([
|
|
164
151
|
r.readContract({ ...c, functionName: "params" }),
|
|
165
152
|
r.readContract({ ...c, functionName: "token" }),
|
|
166
153
|
r.readContract({ ...c, functionName: "phase" }),
|
|
@@ -181,6 +168,8 @@ export class Cloak {
|
|
|
181
168
|
r.readContract({ ...c, functionName: "depositCap" }).catch(() => 0n),
|
|
182
169
|
r.readContract({ ...c, functionName: "creatorOwed" }).catch(() => 0n),
|
|
183
170
|
r.readContract({ ...c, functionName: "feesOwed" }).catch(() => 0n),
|
|
171
|
+
// launches from the Uniswap factory on
|
|
172
|
+
r.readContract({ ...c, functionName: "uniPair" }).catch(() => zeroAddress),
|
|
184
173
|
]);
|
|
185
174
|
const [creator, saleSupply, lpReserve, minPrice, tickSize, numTicks, commitEnd, revealEnd, lpBps, noRevealPenaltyBps, lpLockUntil, tlockRound] = params;
|
|
186
175
|
const [tokenName, tokenSymbol] = await Promise.all([
|
|
@@ -214,6 +203,7 @@ export class Cloak {
|
|
|
214
203
|
sold,
|
|
215
204
|
raised,
|
|
216
205
|
pair,
|
|
206
|
+
uniPair,
|
|
217
207
|
tokenName,
|
|
218
208
|
tokenSymbol,
|
|
219
209
|
launchFeeBps,
|
package/dist/deployments.d.ts
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
|
-
import type { Address } from "viem";
|
|
2
|
-
/** An earlier deployment on the same chain: its launches still list, and
|
|
1
|
+
import type { Address, PublicClient } from "viem";
|
|
2
|
+
/** An earlier deployment on the same chain: its launches still list, and the migrator moves its private balances here. */
|
|
3
3
|
export interface PreviousDeployment {
|
|
4
4
|
version: number;
|
|
5
5
|
factory: Address;
|
|
6
6
|
router: Address;
|
|
7
7
|
routerBlock: bigint;
|
|
8
8
|
batcher?: Address;
|
|
9
|
-
/**
|
|
9
|
+
/** Moved its balances into v3 (v1 and v2 only; from v4 on, the current deployment's `migrator` moves every version). */
|
|
10
10
|
migrator?: Address;
|
|
11
|
+
/** Standalone vaults outside its router (v2's USDC vault), moved too. */
|
|
12
|
+
pools?: {
|
|
13
|
+
pool: Address;
|
|
14
|
+
fromBlock: bigint;
|
|
15
|
+
}[];
|
|
11
16
|
}
|
|
12
17
|
/** Where Cloak lives on each chain, so integrators never copy addresses by hand. */
|
|
13
18
|
export interface CloakDeployment {
|
|
14
19
|
chainId: number;
|
|
15
|
-
/** Which Cloak deployment this is (
|
|
20
|
+
/** Which Cloak deployment this is (4 on Elysium testnet). */
|
|
16
21
|
version: number;
|
|
22
|
+
/** CloakConfig: the rules and the registry of every Cloak contract. `liveDeployment` reads the current ones from it. */
|
|
17
23
|
config: Address;
|
|
24
|
+
/** CloakVaults: the permanent vaults (v4 on). */
|
|
25
|
+
vaults?: Address;
|
|
26
|
+
/** First block of the permanent vaults: scan private notes from here, whichever router is current. */
|
|
27
|
+
vaultsBlock?: bigint;
|
|
18
28
|
factory: Address;
|
|
19
29
|
/** Block the factory was deployed in: scan launch events from here. */
|
|
20
30
|
factoryBlock: bigint;
|
|
31
|
+
/** Earlier factories of this same deployment (newest first): their launches still list, settle and trade. */
|
|
32
|
+
earlierFactories?: Address[];
|
|
33
|
+
/** Block of this deployment's first factory: scan its launches' bids from here (defaults to `factoryBlock`). */
|
|
34
|
+
firstFactoryBlock?: bigint;
|
|
21
35
|
router: Address;
|
|
22
36
|
/** Block the router was deployed in: scan private-pool events from here. */
|
|
23
37
|
routerBlock: bigint;
|
|
24
38
|
batcher: Address;
|
|
25
|
-
/**
|
|
39
|
+
/** Moves balances from every earlier deployment into the permanent vaults. */
|
|
26
40
|
migrator?: Address;
|
|
27
41
|
hypePool: Address;
|
|
28
42
|
whype: Address;
|
|
@@ -42,5 +56,12 @@ export interface CloakDeployment {
|
|
|
42
56
|
previous?: PreviousDeployment[];
|
|
43
57
|
}
|
|
44
58
|
export declare const deployments: Record<number, CloakDeployment>;
|
|
59
|
+
/** Every factory before `d.factory` whose launches should still list, newest first: this deployment's, then earlier ones'. */
|
|
60
|
+
export declare function legacyFactories(d: CloakDeployment): Address[];
|
|
45
61
|
/** The Cloak deployment on `chainId`, or an error naming the chains Cloak is on. */
|
|
46
62
|
export declare function deploymentFor(chainId: number): CloakDeployment;
|
|
63
|
+
/**
|
|
64
|
+
* `base` with the current factory, router, batcher, migrator and vaults read from CloakConfig's registry, so a router or
|
|
65
|
+
* batcher added on-chain is picked up without a new SDK. Earlier deployments keep what `base` knows about them.
|
|
66
|
+
*/
|
|
67
|
+
export declare function liveDeployment(publicClient: PublicClient, base: CloakDeployment): Promise<CloakDeployment>;
|
package/dist/deployments.js
CHANGED
|
@@ -1,31 +1,51 @@
|
|
|
1
|
+
import { privateRouterAbi } from "./abis.js";
|
|
2
|
+
import { readRegistry } from "./registry.js";
|
|
1
3
|
export const deployments = {
|
|
2
|
-
// Cloak
|
|
4
|
+
// Cloak v4 (Oct 31), the permanent vaults, plus the Uniswap launch factory (Nov 2): deployments/elysium-testnet-v4.json. CloakConfig's registry lists all of it;
|
|
5
|
+
// liveDeployment() reads the current contracts from there.
|
|
3
6
|
99801: {
|
|
4
7
|
chainId: 99801,
|
|
5
|
-
version:
|
|
6
|
-
config: "
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
version: 4,
|
|
9
|
+
config: "0x9fdf166f0671166148ea98cdd3ef0118d256167f",
|
|
10
|
+
vaults: "0x24bc1d369aab3a2d741a48f8cac1af5dfd9f3d43",
|
|
11
|
+
vaultsBlock: 19485039n,
|
|
12
|
+
// the Uniswap launch factory (Nov 2): every launch opens a Uniswap V2 pool at its clearing price
|
|
13
|
+
factory: "0xeac84944f5a8343edf49cde8ef74d71f4908a656",
|
|
14
|
+
factoryBlock: 21221250n,
|
|
15
|
+
earlierFactories: ["0xa88df63d7d44acc66052e5cbe5ba9503bf940993"],
|
|
16
|
+
firstFactoryBlock: 19484794n,
|
|
17
|
+
router: "0x343ab9a7aac93cee28321410510ea24417cc6386",
|
|
18
|
+
routerBlock: 19485063n,
|
|
19
|
+
batcher: "0xc69e4bca18020ae93bc9f17093985bfb139a3203",
|
|
20
|
+
migrator: "0x86c5d8035224493f10938aaa07b179be316dadf4",
|
|
21
|
+
hypePool: "0x3ACB22829bb422446caaDd8546e65ab530A53031",
|
|
14
22
|
whype: "0xe44b27113D4b947c0B1bDf4a93878D0e115f4bdD",
|
|
15
23
|
relayerUrl: "https://cloak-keeper.onrender.com",
|
|
16
24
|
circuitsUrl: "https://cloak.boblabs.tech/circuits",
|
|
17
25
|
assets: [
|
|
18
26
|
// Elysium testnet USDC (bridged from Circle's USDC on HyperEVM): private sends and withdrawals
|
|
19
|
-
{ symbol: "USDC", token: "0x7D29d8047B905000459c0E80c34a26CeedcB47b2", pool: "
|
|
27
|
+
{ symbol: "USDC", token: "0x7D29d8047B905000459c0E80c34a26CeedcB47b2", pool: "0x3d5cB722490D9908a118f8B3151f83fcE943E4F0", decimals: 6, fromBlock: 19485039n },
|
|
20
28
|
],
|
|
21
29
|
previous: [
|
|
30
|
+
{
|
|
31
|
+
version: 3,
|
|
32
|
+
factory: "0xd0f4aacf339f07211a9155194925b2f94e250e29",
|
|
33
|
+
router: "0x78319bee7c21ca411166acc67c750aca10280e86",
|
|
34
|
+
routerBlock: 19096485n,
|
|
35
|
+
batcher: "0x9902d86c5be81f6c6ce059acf4c89193d06069c4",
|
|
36
|
+
pools: [
|
|
37
|
+
{ pool: "0x61de30970e3c53665ce5a89323284e7ab379fa08", fromBlock: 18329466n },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
22
40
|
{
|
|
23
41
|
version: 2,
|
|
24
42
|
factory: "0xc1fc14e84cbbd10f75dad9d91bf50f47c48757fc",
|
|
25
43
|
router: "0xd51e731467c49991496329c2b7979cb1aa220ee2",
|
|
26
44
|
routerBlock: 15856031n,
|
|
27
45
|
batcher: "0xa13ffd763a8cccfea1b868c616291723579ddb77",
|
|
28
|
-
|
|
46
|
+
pools: [
|
|
47
|
+
{ pool: "0x61de30970e3c53665ce5a89323284e7ab379fa08", fromBlock: 18329466n },
|
|
48
|
+
],
|
|
29
49
|
},
|
|
30
50
|
{
|
|
31
51
|
version: 1,
|
|
@@ -33,11 +53,14 @@ export const deployments = {
|
|
|
33
53
|
router: "0xfa2574cfc3afb8f7d3a0651fa2111ff4e3d2fc41",
|
|
34
54
|
routerBlock: 10973723n,
|
|
35
55
|
batcher: "0xf6582cc5a84fccf74e571e652fb7b603a2c25812",
|
|
36
|
-
migrator: "0x5f3d82a6aa1b20ba9d0f58a98d1c4933c115a0da",
|
|
37
56
|
},
|
|
38
57
|
],
|
|
39
58
|
},
|
|
40
59
|
};
|
|
60
|
+
/** Every factory before `d.factory` whose launches should still list, newest first: this deployment's, then earlier ones'. */
|
|
61
|
+
export function legacyFactories(d) {
|
|
62
|
+
return [...(d.earlierFactories ?? []), ...(d.previous ?? []).map((p) => p.factory)].filter((f) => f && !/^0x0{40}$/i.test(f));
|
|
63
|
+
}
|
|
41
64
|
/** The Cloak deployment on `chainId`, or an error naming the chains Cloak is on. */
|
|
42
65
|
export function deploymentFor(chainId) {
|
|
43
66
|
const d = deployments[chainId];
|
|
@@ -45,3 +68,46 @@ export function deploymentFor(chainId) {
|
|
|
45
68
|
throw new Error(`Cloak isn't deployed on chain ${chainId} (available: ${Object.keys(deployments).join(", ")})`);
|
|
46
69
|
return d;
|
|
47
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* `base` with the current factory, router, batcher, migrator and vaults read from CloakConfig's registry, so a router or
|
|
73
|
+
* batcher added on-chain is picked up without a new SDK. Earlier deployments keep what `base` knows about them.
|
|
74
|
+
*/
|
|
75
|
+
export async function liveDeployment(publicClient, base) {
|
|
76
|
+
const reg = await readRegistry(publicClient, base.config).catch(() => undefined);
|
|
77
|
+
if (!reg)
|
|
78
|
+
return base;
|
|
79
|
+
const [hypePool, whype] = await Promise.all([
|
|
80
|
+
publicClient.readContract({ address: reg.router, abi: privateRouterAbi, functionName: "hypePool" }),
|
|
81
|
+
publicClient.readContract({ address: reg.router, abi: privateRouterAbi, functionName: "whype" }),
|
|
82
|
+
]);
|
|
83
|
+
const known = new Map((base.previous ?? []).map((p) => [p.version, p]));
|
|
84
|
+
return {
|
|
85
|
+
...base,
|
|
86
|
+
version: reg.version,
|
|
87
|
+
vaults: reg.vaults ?? base.vaults,
|
|
88
|
+
vaultsBlock: reg.vaultsBlock ?? base.vaultsBlock,
|
|
89
|
+
factory: reg.factory,
|
|
90
|
+
factoryBlock: reg.factoryBlock,
|
|
91
|
+
earlierFactories: reg.earlierFactories.length ? reg.earlierFactories : base.earlierFactories,
|
|
92
|
+
router: reg.router,
|
|
93
|
+
routerBlock: reg.routerBlock,
|
|
94
|
+
batcher: reg.batcher ?? base.batcher,
|
|
95
|
+
migrator: reg.migrator ?? base.migrator,
|
|
96
|
+
hypePool,
|
|
97
|
+
whype,
|
|
98
|
+
previous: reg.previous.length
|
|
99
|
+
? reg.previous.map((p) => {
|
|
100
|
+
const k = known.get(p.version);
|
|
101
|
+
return {
|
|
102
|
+
version: p.version,
|
|
103
|
+
factory: p.factory ?? k?.factory ?? ("0x" + "0".repeat(40)),
|
|
104
|
+
router: p.router ?? k?.router ?? ("0x" + "0".repeat(40)),
|
|
105
|
+
routerBlock: p.routerBlock ?? k?.routerBlock ?? 0n,
|
|
106
|
+
batcher: p.batcher ?? k?.batcher,
|
|
107
|
+
migrator: k?.migrator,
|
|
108
|
+
pools: p.pools.length ? p.pools.map((x) => ({ pool: x.addr, fromBlock: x.startBlock })) : k?.pools,
|
|
109
|
+
};
|
|
110
|
+
})
|
|
111
|
+
: base.previous,
|
|
112
|
+
};
|
|
113
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/private/client.d.ts
CHANGED
|
@@ -70,17 +70,32 @@ export declare class CloakPrivate {
|
|
|
70
70
|
})[];
|
|
71
71
|
constructor(publicClient: PublicClient, router: Address, keys: CloakKeys, prover: () => Promise<Prover>, submit: Submitter, fromBlock?: bigint, batcher?: Address | undefined, migrator?: Address | undefined);
|
|
72
72
|
/**
|
|
73
|
-
* Derive the private
|
|
74
|
-
*
|
|
75
|
-
*
|
|
73
|
+
* Derive the wallet's Cloak private account from one EIP-712 signature bound to this chain (never to a contract, so
|
|
74
|
+
* the account survives every upgrade). With `verify`, the wallet signs twice and the keys are refused if the two
|
|
75
|
+
* signatures differ (some smart and MPC wallets sign differently each time, which would hide earlier notes).
|
|
76
76
|
*/
|
|
77
77
|
static keysFromWallet(wallet: Wallet, opts: {
|
|
78
78
|
chainId: number;
|
|
79
|
-
router: Address;
|
|
80
79
|
verify?: boolean;
|
|
81
80
|
}): Promise<CloakKeys>;
|
|
81
|
+
/** Keys of a v2 or v3 account, bound to that deployment's router. Only needed to move an old balance across. */
|
|
82
|
+
static routerKeysFromWallet(wallet: Wallet, opts: {
|
|
83
|
+
chainId: number;
|
|
84
|
+
router: Address;
|
|
85
|
+
}): Promise<CloakKeys>;
|
|
86
|
+
/** The keys an earlier deployment's notes were made for: v1 a plain message, v2 and v3 their router, v4 on the account. */
|
|
87
|
+
static keysForVersion(wallet: Wallet, opts: {
|
|
88
|
+
chainId: number;
|
|
89
|
+
version: number;
|
|
90
|
+
router: Address;
|
|
91
|
+
}): Promise<CloakKeys>;
|
|
92
|
+
private static signedKeys;
|
|
82
93
|
/** Keys of the first Cloak deployment (plain signed message). Only needed to move an old balance across. */
|
|
83
94
|
static legacyKeysFromWallet(wallet: Wallet): Promise<CloakKeys>;
|
|
95
|
+
/**
|
|
96
|
+
* Read the router's vaults: HYPE first, then every launch market. A vault without a launch pair (USDC) is an asset,
|
|
97
|
+
* not a market, and is added to `assets` instead.
|
|
98
|
+
*/
|
|
84
99
|
loadMarkets(): Promise<PrivateMarket[]>;
|
|
85
100
|
get hypeMarket(): PrivateMarket;
|
|
86
101
|
market(token: Address): PrivateMarket;
|
|
@@ -116,6 +131,15 @@ export declare class CloakPrivate {
|
|
|
116
131
|
* one step is public and lands on a one-time key. Asks the wallet to approve the pool first if needed.
|
|
117
132
|
*/
|
|
118
133
|
shieldToken(wallet: Wallet, token: Address, amount: bigint, onStatus?: Status): Promise<Hex>;
|
|
134
|
+
/**
|
|
135
|
+
* Claim a won sealed bid straight into the private vault (v4 launches): the tokens become a note for a one-time key,
|
|
136
|
+
* so later trades can't be linked to the bid. Sent from the bidder's wallet (only the bidder can claim this way); the
|
|
137
|
+
* HYPE refund, if any, still goes to the wallet. The token's vault must exist (the keeper opens it at settlement).
|
|
138
|
+
*/
|
|
139
|
+
claimPrivately(wallet: Wallet, auction: Address, bidId: bigint): Promise<{
|
|
140
|
+
txHash: Hex;
|
|
141
|
+
tokens: bigint;
|
|
142
|
+
}>;
|
|
119
143
|
roundInfo(): Promise<{
|
|
120
144
|
round: bigint;
|
|
121
145
|
endsAt: number;
|
package/dist/private/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encodeAbiParameters, parseEventLogs, zeroAddress } from "viem";
|
|
2
|
-
import { cloakMigratorAbi, cloakPairAbi, privateBatcherAbi, privateRouterAbi, shieldedPoolAbi } from "../abis.js";
|
|
3
|
-
import { ACCOUNT_MESSAGE, ACCOUNT_TYPED_DATA, CloakKeys, MAIN_KEY, noteCommitment, encryptFullMemo, encryptRouterMemo, formatCloakAddress, nullifierOf, parseCloakAddress, randomField, randomKeyIndex, readMemo, } from "./crypto.js";
|
|
2
|
+
import { cloakAuctionAbi, cloakMigratorAbi, cloakPairAbi, privateBatcherAbi, privateRouterAbi, shieldedPoolAbi } from "../abis.js";
|
|
3
|
+
import { ACCOUNT_MESSAGE, ACCOUNT_TYPED_DATA, ROUTER_ACCOUNT_TYPED_DATA, CloakKeys, MAIN_KEY, noteCommitment, encryptFullMemo, encryptRouterMemo, formatCloakAddress, nullifierOf, parseCloakAddress, randomField, randomKeyIndex, readMemo, } from "./crypto.js";
|
|
4
4
|
import { MerkleTree } from "./tree.js";
|
|
5
5
|
import { MOVE_DATA_ABI, ORDER_DATA_ABI, SWAP_DATA_ABI, buildTransaction, selectNotes, splitStandard } from "./tx.js";
|
|
6
6
|
/** Leaf positions per tree epoch (a pool starts a new tree after 2^20 leaves). */
|
|
@@ -11,6 +11,8 @@ const ERC20_ABI = [
|
|
|
11
11
|
{ type: "function", name: "allowance", stateMutability: "view", inputs: [{ type: "address" }, { type: "address" }], outputs: [{ type: "uint256" }] },
|
|
12
12
|
{ type: "function", name: "approve", stateMutability: "nonpayable", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }] },
|
|
13
13
|
{ type: "function", name: "balanceOf", stateMutability: "view", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }] },
|
|
14
|
+
{ type: "function", name: "symbol", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
|
|
15
|
+
{ type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
|
|
14
16
|
];
|
|
15
17
|
const json = (v) => JSON.stringify(v, (_, x) => (typeof x === "bigint" ? x.toString() : x));
|
|
16
18
|
/** POST shielded calls to a Cloak relayer (`services/keeper` serves `/relay` and `/quote`). */
|
|
@@ -96,14 +98,30 @@ export class CloakPrivate {
|
|
|
96
98
|
this.migrator = migrator;
|
|
97
99
|
}
|
|
98
100
|
/**
|
|
99
|
-
* Derive the private
|
|
100
|
-
*
|
|
101
|
-
*
|
|
101
|
+
* Derive the wallet's Cloak private account from one EIP-712 signature bound to this chain (never to a contract, so
|
|
102
|
+
* the account survives every upgrade). With `verify`, the wallet signs twice and the keys are refused if the two
|
|
103
|
+
* signatures differ (some smart and MPC wallets sign differently each time, which would hide earlier notes).
|
|
102
104
|
*/
|
|
103
105
|
static async keysFromWallet(wallet, opts) {
|
|
104
|
-
|
|
106
|
+
return CloakPrivate.signedKeys(wallet, ACCOUNT_TYPED_DATA(opts.chainId), opts.verify);
|
|
107
|
+
}
|
|
108
|
+
/** Keys of a v2 or v3 account, bound to that deployment's router. Only needed to move an old balance across. */
|
|
109
|
+
static async routerKeysFromWallet(wallet, opts) {
|
|
110
|
+
return CloakPrivate.signedKeys(wallet, ROUTER_ACCOUNT_TYPED_DATA(opts.chainId, opts.router), false);
|
|
111
|
+
}
|
|
112
|
+
/** The keys an earlier deployment's notes were made for: v1 a plain message, v2 and v3 their router, v4 on the account. */
|
|
113
|
+
static async keysForVersion(wallet, opts) {
|
|
114
|
+
if (opts.version <= 1)
|
|
115
|
+
return CloakPrivate.legacyKeysFromWallet(wallet);
|
|
116
|
+
if (opts.version <= 3)
|
|
117
|
+
return CloakPrivate.routerKeysFromWallet(wallet, opts);
|
|
118
|
+
return CloakPrivate.keysFromWallet(wallet, opts);
|
|
119
|
+
}
|
|
120
|
+
static async signedKeys(wallet, typed, verify) {
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
const req = { account: wallet.account, ...typed };
|
|
105
123
|
const sig = await wallet.signTypedData(req);
|
|
106
|
-
if (
|
|
124
|
+
if (verify) {
|
|
107
125
|
const again = await wallet.signTypedData(req);
|
|
108
126
|
if (again.toLowerCase() !== sig.toLowerCase()) {
|
|
109
127
|
throw new Error("This wallet gives a different signature each time, so it can't hold a Cloak private account. Use a standard wallet such as MetaMask or Rabby.");
|
|
@@ -116,20 +134,42 @@ export class CloakPrivate {
|
|
|
116
134
|
const sig = await wallet.signMessage({ account: wallet.account, message: ACCOUNT_MESSAGE });
|
|
117
135
|
return CloakKeys.fromSignature(sig);
|
|
118
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Read the router's vaults: HYPE first, then every launch market. A vault without a launch pair (USDC) is an asset,
|
|
139
|
+
* not a market, and is added to `assets` instead.
|
|
140
|
+
*/
|
|
119
141
|
async loadMarkets() {
|
|
120
142
|
const c = { address: this.router, abi: privateRouterAbi };
|
|
121
|
-
const n = await
|
|
143
|
+
const [n, whype] = await Promise.all([
|
|
144
|
+
this.publicClient.readContract({ ...c, functionName: "tokensCount" }),
|
|
145
|
+
this.publicClient.readContract({ ...c, functionName: "whype" }),
|
|
146
|
+
]);
|
|
147
|
+
const tokens = await Promise.all(Array.from({ length: Number(n) }, (_, i) => this.publicClient.readContract({ ...c, functionName: "tokens", args: [BigInt(i)] })));
|
|
148
|
+
const rows = await Promise.all(tokens.map((token) => Promise.all([
|
|
149
|
+
this.publicClient.readContract({ ...c, functionName: "poolOf", args: [token] }),
|
|
150
|
+
this.publicClient.readContract({ ...c, functionName: "pairOf", args: [token] }),
|
|
151
|
+
])));
|
|
122
152
|
const out = [];
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const [pool, pair] =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
153
|
+
let hype;
|
|
154
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
155
|
+
const [pool, pair] = rows[i];
|
|
156
|
+
const token = tokens[i];
|
|
157
|
+
if (token.toLowerCase() === whype.toLowerCase())
|
|
158
|
+
hype = { token, pool, pair: null };
|
|
159
|
+
else if (pair !== zeroAddress)
|
|
160
|
+
out.push({ token, pool, pair });
|
|
161
|
+
else if (!this.assets.some((a) => a.pool.toLowerCase() === pool.toLowerCase())) {
|
|
162
|
+
const [symbol, decimals] = await Promise.all([
|
|
163
|
+
this.publicClient.readContract({ address: token, abi: ERC20_ABI, functionName: "symbol" }).catch(() => "?"),
|
|
164
|
+
this.publicClient.readContract({ address: token, abi: ERC20_ABI, functionName: "decimals" }).catch(() => 18),
|
|
165
|
+
]);
|
|
166
|
+
this.addAsset({ symbol, token, pool, decimals: Number(decimals), fromBlock: this.fromBlock });
|
|
167
|
+
}
|
|
130
168
|
}
|
|
131
|
-
|
|
132
|
-
|
|
169
|
+
if (!hype)
|
|
170
|
+
throw new Error("the router has no HYPE vault");
|
|
171
|
+
this.markets = [hype, ...out];
|
|
172
|
+
return this.markets;
|
|
133
173
|
}
|
|
134
174
|
get hypeMarket() {
|
|
135
175
|
const m = this.markets[0];
|
|
@@ -343,6 +383,29 @@ export class CloakPrivate {
|
|
|
343
383
|
throw new Error("shield reverted");
|
|
344
384
|
return hash;
|
|
345
385
|
}
|
|
386
|
+
/**
|
|
387
|
+
* Claim a won sealed bid straight into the private vault (v4 launches): the tokens become a note for a one-time key,
|
|
388
|
+
* so later trades can't be linked to the bid. Sent from the bidder's wallet (only the bidder can claim this way); the
|
|
389
|
+
* HYPE refund, if any, still goes to the wallet. The token's vault must exist (the keeper opens it at settlement).
|
|
390
|
+
*/
|
|
391
|
+
async claimPrivately(wallet, auction, bidId) {
|
|
392
|
+
const [tokens] = await this.publicClient.readContract({ address: auction, abi: cloakAuctionAbi, functionName: "allocationOf", args: [bidId] });
|
|
393
|
+
if (tokens === 0n)
|
|
394
|
+
throw new Error("this bid won no tokens");
|
|
395
|
+
const keyIndex = randomKeyIndex();
|
|
396
|
+
const k = await this.keys.key(keyIndex);
|
|
397
|
+
const blinding = randomField();
|
|
398
|
+
const hash = await wallet.writeContract({
|
|
399
|
+
address: auction,
|
|
400
|
+
abi: cloakAuctionAbi,
|
|
401
|
+
functionName: "claimPrivate",
|
|
402
|
+
args: [bidId, k.pubKey, blinding, encryptFullMemo(this.keys.encPub, tokens, blinding, keyIndex)],
|
|
403
|
+
});
|
|
404
|
+
const r = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
405
|
+
if (r.status !== "success")
|
|
406
|
+
throw new Error("private claim reverted");
|
|
407
|
+
return { txHash: hash, tokens };
|
|
408
|
+
}
|
|
346
409
|
// ───────────── batch auctions (hide trade size) ─────────────
|
|
347
410
|
async roundInfo() {
|
|
348
411
|
if (!this.batcher)
|
|
@@ -571,11 +634,12 @@ export class CloakPrivate {
|
|
|
571
634
|
async migrateFrom(legacy, onStatus = () => { }, opts = {}) {
|
|
572
635
|
const migrator = opts.migrator ?? this.migratorAddress();
|
|
573
636
|
const moved = [];
|
|
574
|
-
const markets = await legacy.loadMarkets();
|
|
637
|
+
const markets = [...(await legacy.loadMarkets()), ...legacy.assets];
|
|
575
638
|
await this.loadMarkets();
|
|
639
|
+
const here = [...this.markets, ...this.assets];
|
|
576
640
|
for (const m of markets) {
|
|
577
|
-
if (!
|
|
578
|
-
continue; // no
|
|
641
|
+
if (!here.some((x) => x.token.toLowerCase() === m.token.toLowerCase()))
|
|
642
|
+
continue; // no vault here yet
|
|
579
643
|
for (;;) {
|
|
580
644
|
const live = (await legacy.sync(m.pool)).sort((a, b) => (a.amount > b.amount ? -1 : 1));
|
|
581
645
|
if (!live.length)
|