@cloakely/sdk 0.2.4 → 0.2.5
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/README.md +10 -1
- package/dist/deployments.d.ts +8 -0
- package/dist/deployments.js +4 -0
- package/dist/private/client.d.ts +24 -2
- package/dist/private/client.js +53 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,15 @@ await priv.unshieldHype(freshAddress, parseEther("0.5")); // back to any wallet
|
|
|
72
72
|
console.log(await priv.balance(priv.hypeMarket.pool)); // only this account can see it
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
Private USDC lives in its own vault. Register it from the deployment, then shield, send and withdraw like any token:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const usdc = priv.addAsset(d.assets![0]); // { symbol: "USDC", decimals: 6, … }
|
|
79
|
+
await priv.shieldToken(walletClient, usdc.token, parseUnits("50", 6)); // approve + deposit (public, once)
|
|
80
|
+
await priv.send(usdc.token, "cloak:…", parseUnits("20", 6)); // amount hidden
|
|
81
|
+
await priv.unshieldToken(usdc.token, freshAddress, parseUnits("10", 6)); // 0.25% fee kept
|
|
82
|
+
```
|
|
83
|
+
|
|
75
84
|
The private account comes from one EIP-712 signature bound to the chain and the router. The same wallet always restores it, and nothing is stored on a server. In Node, read the circuit files yourself and pass them to `createProver(wasm, zkey)`.
|
|
76
85
|
|
|
77
86
|
## Fees (testnet beta)
|
|
@@ -90,7 +99,7 @@ Rules live in the on-chain `CloakConfig`. Raising a fee or a cap waits a public
|
|
|
90
99
|
| Export | What it is |
|
|
91
100
|
|---|---|
|
|
92
101
|
| `Cloak` | Launches: `createLaunch`, `bid`, `revealAll`, `settle`, `claimAll`, `payOut`, `getAuction`, `listLaunches` |
|
|
93
|
-
| `CloakPrivate` | Private balances: `shieldHype`, `buy`, `sell`, `batch`, `send`, `unshieldHype`, `unshieldToken`, `balance`, `maxSpendable`, `migrateFrom` |
|
|
102
|
+
| `CloakPrivate` | Private balances: `shieldHype`, `shieldToken`, `buy`, `sell`, `batch`, `send`, `unshieldHype`, `unshieldToken`, `addAsset`, `balance`, `maxSpendable`, `migrateFrom` |
|
|
94
103
|
| `relayerSubmitter`, `walletSubmitter` | How private calls are submitted: through a relayer (private), or from a wallet (for tests) |
|
|
95
104
|
| `loadProver`, `createProver` | The Groth16 prover, running on the device |
|
|
96
105
|
| `deployments`, `deploymentFor` | Addresses, start blocks, relayer and circuit URLs per chain |
|
package/dist/deployments.d.ts
CHANGED
|
@@ -15,6 +15,14 @@ export interface CloakDeployment {
|
|
|
15
15
|
relayerUrl: string;
|
|
16
16
|
/** Hosted circuit artifacts (transaction2x2.wasm and transaction2x2_final.zkey). */
|
|
17
17
|
circuitsUrl: string;
|
|
18
|
+
/** Shielded pools for existing tokens (USDC): register them with `CloakPrivate.addAsset`. */
|
|
19
|
+
assets?: {
|
|
20
|
+
symbol: string;
|
|
21
|
+
token: Address;
|
|
22
|
+
pool: Address;
|
|
23
|
+
decimals: number;
|
|
24
|
+
fromBlock: bigint;
|
|
25
|
+
}[];
|
|
18
26
|
/** The first deployment: its launches still list, and its private balances move here through `migrator`. */
|
|
19
27
|
legacy?: {
|
|
20
28
|
factory: Address;
|
package/dist/deployments.js
CHANGED
|
@@ -11,6 +11,10 @@ export const deployments = {
|
|
|
11
11
|
whype: "0xe44b27113D4b947c0B1bDf4a93878D0e115f4bdD",
|
|
12
12
|
relayerUrl: "https://cloak-keeper.onrender.com",
|
|
13
13
|
circuitsUrl: "https://cloak.boblabs.tech/circuits",
|
|
14
|
+
assets: [
|
|
15
|
+
// Elysium testnet USDC (bridged from Circle's USDC on HyperEVM): private sends and withdrawals
|
|
16
|
+
{ symbol: "USDC", token: "0x7D29d8047B905000459c0E80c34a26CeedcB47b2", pool: "0x61de30970e3c53665ce5a89323284e7ab379fa08", decimals: 6, fromBlock: 18329466n },
|
|
17
|
+
],
|
|
14
18
|
legacy: {
|
|
15
19
|
factory: "0x1dc1ea9837ecbd31ec74f0d558e1db1c303a7e1c",
|
|
16
20
|
router: "0xfa2574cfc3afb8f7d3a0651fa2111ff4e3d2fc41",
|
package/dist/private/client.d.ts
CHANGED
|
@@ -26,6 +26,17 @@ export interface PrivateMarket {
|
|
|
26
26
|
pool: Address;
|
|
27
27
|
pair: Address | null;
|
|
28
28
|
symbol?: string;
|
|
29
|
+
/** Token decimals (18 for HYPE and launch tokens; 6 for USDC). */
|
|
30
|
+
decimals?: number;
|
|
31
|
+
}
|
|
32
|
+
/** A shielded pool for an existing token (such as USDC) that lives next to the router, not in its launch registry. */
|
|
33
|
+
export interface PrivateAsset {
|
|
34
|
+
symbol: string;
|
|
35
|
+
token: Address;
|
|
36
|
+
pool: Address;
|
|
37
|
+
decimals: number;
|
|
38
|
+
/** Block the pool was deployed in: its events are scanned from here. */
|
|
39
|
+
fromBlock: bigint;
|
|
29
40
|
}
|
|
30
41
|
/** POST shielded calls to a Cloak relayer (`services/keeper` serves `/relay` and `/quote`). */
|
|
31
42
|
export declare function relayerSubmitter(url: string): Submitter;
|
|
@@ -51,6 +62,10 @@ export declare class CloakPrivate {
|
|
|
51
62
|
readonly migrator?: Address | undefined;
|
|
52
63
|
private pools;
|
|
53
64
|
markets: PrivateMarket[];
|
|
65
|
+
/** Shielded pools outside the launch registry (USDC). Send, unshieldToken and shieldToken work on these too. */
|
|
66
|
+
assets: (PrivateMarket & {
|
|
67
|
+
fromBlock: bigint;
|
|
68
|
+
})[];
|
|
54
69
|
constructor(publicClient: PublicClient, router: Address, keys: CloakKeys, prover: () => Promise<Prover>, submit: Submitter, fromBlock?: bigint, batcher?: Address | undefined, migrator?: Address | undefined);
|
|
55
70
|
/**
|
|
56
71
|
* Derive the private keys from one EIP-712 signature bound to this chain and router, so a signature asked for by any
|
|
@@ -67,6 +82,8 @@ export declare class CloakPrivate {
|
|
|
67
82
|
loadMarkets(): Promise<PrivateMarket[]>;
|
|
68
83
|
get hypeMarket(): PrivateMarket;
|
|
69
84
|
market(token: Address): PrivateMarket;
|
|
85
|
+
/** Register a shielded pool that isn't a launch market, such as USDC (`deploymentFor(chainId).assets`). */
|
|
86
|
+
addAsset(a: PrivateAsset): PrivateMarket;
|
|
70
87
|
private state;
|
|
71
88
|
/** Pull new leaves from the pool's events, trial-decrypt them, and refresh spent flags. */
|
|
72
89
|
sync(pool: Address): Promise<OwnedNote[]>;
|
|
@@ -92,6 +109,11 @@ export declare class CloakPrivate {
|
|
|
92
109
|
private inputsFor;
|
|
93
110
|
/** Public HYPE → private balance. This one step is public (your wallet deposits); everything after is not. */
|
|
94
111
|
shieldHype(wallet: Wallet, amount: bigint): Promise<Hex>;
|
|
112
|
+
/**
|
|
113
|
+
* Public tokens → private balance, for any pool this client knows (USDC, or a launch token). Like shieldHype, this
|
|
114
|
+
* one step is public and lands on a one-time key. Asks the wallet to approve the pool first if needed.
|
|
115
|
+
*/
|
|
116
|
+
shieldToken(wallet: Wallet, token: Address, amount: bigint, onStatus?: Status): Promise<Hex>;
|
|
95
117
|
roundInfo(): Promise<{
|
|
96
118
|
round: bigint;
|
|
97
119
|
endsAt: number;
|
|
@@ -143,10 +165,10 @@ export declare class CloakPrivate {
|
|
|
143
165
|
address(): Promise<string>;
|
|
144
166
|
/**
|
|
145
167
|
* Private transfer inside a pool: sender, recipient and amount all stay hidden.
|
|
146
|
-
* `token` = a launch token, or the WHYPE address / hypeMarket.token for HYPE.
|
|
168
|
+
* `token` = a launch token, an asset such as USDC, or the WHYPE address / hypeMarket.token for HYPE.
|
|
147
169
|
*/
|
|
148
170
|
send(token: Address, to: string, amount: bigint, onStatus?: Status): Promise<Hex>;
|
|
149
|
-
/** Private launch
|
|
171
|
+
/** Private tokens (a launch token, or an asset such as USDC) → any address. */
|
|
150
172
|
unshieldToken(token: Address, to: Address, amount: bigint, onStatus?: Status): Promise<Hex>;
|
|
151
173
|
/**
|
|
152
174
|
* Move every private balance `legacy` (a client on the earlier router, with the earlier keys) can see into this
|
package/dist/private/client.js
CHANGED
|
@@ -7,6 +7,10 @@ import { MOVE_DATA_ABI, ORDER_DATA_ABI, SWAP_DATA_ABI, buildTransaction, selectN
|
|
|
7
7
|
const EPOCH_BITS = 20;
|
|
8
8
|
const epochOf = (globalIndex) => Math.floor(globalIndex / 2 ** EPOCH_BITS);
|
|
9
9
|
const positionOf = (globalIndex) => globalIndex % 2 ** EPOCH_BITS;
|
|
10
|
+
const ERC20_ABI = [
|
|
11
|
+
{ type: "function", name: "allowance", stateMutability: "view", inputs: [{ type: "address" }, { type: "address" }], outputs: [{ type: "uint256" }] },
|
|
12
|
+
{ type: "function", name: "approve", stateMutability: "nonpayable", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }] },
|
|
13
|
+
];
|
|
10
14
|
const json = (v) => JSON.stringify(v, (_, x) => (typeof x === "bigint" ? x.toString() : x));
|
|
11
15
|
/** POST shielded calls to a Cloak relayer (`services/keeper` serves `/relay` and `/quote`). */
|
|
12
16
|
export function relayerSubmitter(url) {
|
|
@@ -75,6 +79,8 @@ export class CloakPrivate {
|
|
|
75
79
|
migrator;
|
|
76
80
|
pools = new Map();
|
|
77
81
|
markets = [];
|
|
82
|
+
/** Shielded pools outside the launch registry (USDC). Send, unshieldToken and shieldToken work on these too. */
|
|
83
|
+
assets = [];
|
|
78
84
|
constructor(publicClient, router, keys, prover, submit, fromBlock = 0n, batcher, migrator) {
|
|
79
85
|
this.publicClient = publicClient;
|
|
80
86
|
this.router = router;
|
|
@@ -128,15 +134,26 @@ export class CloakPrivate {
|
|
|
128
134
|
return m;
|
|
129
135
|
}
|
|
130
136
|
market(token) {
|
|
131
|
-
const
|
|
137
|
+
const t = token.toLowerCase();
|
|
138
|
+
const m = this.markets.find((x) => x.token.toLowerCase() === t) ?? this.assets.find((x) => x.token.toLowerCase() === t);
|
|
132
139
|
if (!m)
|
|
133
140
|
throw new Error("no private market for this token (createPool after settlement)");
|
|
134
141
|
return m;
|
|
135
142
|
}
|
|
143
|
+
/** Register a shielded pool that isn't a launch market, such as USDC (`deploymentFor(chainId).assets`). */
|
|
144
|
+
addAsset(a) {
|
|
145
|
+
const existing = this.assets.find((x) => x.pool.toLowerCase() === a.pool.toLowerCase());
|
|
146
|
+
if (existing)
|
|
147
|
+
return existing;
|
|
148
|
+
const m = { token: a.token, pool: a.pool, pair: null, symbol: a.symbol, decimals: a.decimals, fromBlock: a.fromBlock };
|
|
149
|
+
this.assets.push(m);
|
|
150
|
+
return m;
|
|
151
|
+
}
|
|
136
152
|
state(pool) {
|
|
137
153
|
let s = this.pools.get(pool.toLowerCase());
|
|
138
154
|
if (!s) {
|
|
139
|
-
|
|
155
|
+
const asset = this.assets.find((x) => x.pool.toLowerCase() === pool.toLowerCase());
|
|
156
|
+
s = { leaves: [], scannedUpTo: 0, fromBlock: asset?.fromBlock ?? this.fromBlock, notes: [] };
|
|
140
157
|
this.pools.set(pool.toLowerCase(), s);
|
|
141
158
|
}
|
|
142
159
|
return s;
|
|
@@ -286,6 +303,38 @@ export class CloakPrivate {
|
|
|
286
303
|
throw new Error("shield reverted");
|
|
287
304
|
return hash;
|
|
288
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Public tokens → private balance, for any pool this client knows (USDC, or a launch token). Like shieldHype, this
|
|
308
|
+
* one step is public and lands on a one-time key. Asks the wallet to approve the pool first if needed.
|
|
309
|
+
*/
|
|
310
|
+
async shieldToken(wallet, token, amount, onStatus = () => { }) {
|
|
311
|
+
if (amount <= 0n)
|
|
312
|
+
throw new Error("amount must be positive");
|
|
313
|
+
const pool = this.market(token).pool;
|
|
314
|
+
const owner = wallet.account.address;
|
|
315
|
+
const allowance = await this.publicClient.readContract({ address: token, abi: ERC20_ABI, functionName: "allowance", args: [owner, pool] });
|
|
316
|
+
if (allowance < amount) {
|
|
317
|
+
onStatus("Approve the deposit in your wallet…");
|
|
318
|
+
const a = await wallet.writeContract({ address: token, abi: ERC20_ABI, functionName: "approve", args: [pool, amount] });
|
|
319
|
+
const ar = await this.publicClient.waitForTransactionReceipt({ hash: a });
|
|
320
|
+
if (ar.status !== "success")
|
|
321
|
+
throw new Error("approve reverted");
|
|
322
|
+
}
|
|
323
|
+
const keyIndex = randomKeyIndex();
|
|
324
|
+
const k = await this.keys.key(keyIndex);
|
|
325
|
+
const blinding = randomField();
|
|
326
|
+
onStatus("Confirm the deposit in your wallet…");
|
|
327
|
+
const hash = await wallet.writeContract({
|
|
328
|
+
address: pool,
|
|
329
|
+
abi: shieldedPoolAbi,
|
|
330
|
+
functionName: "depositTo",
|
|
331
|
+
args: [k.pubKey, amount, blinding, encryptFullMemo(this.keys.encPub, amount, blinding, keyIndex)],
|
|
332
|
+
});
|
|
333
|
+
const r = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
334
|
+
if (r.status !== "success")
|
|
335
|
+
throw new Error("shield reverted");
|
|
336
|
+
return hash;
|
|
337
|
+
}
|
|
289
338
|
// ───────────── batch auctions (hide trade size) ─────────────
|
|
290
339
|
async roundInfo() {
|
|
291
340
|
if (!this.batcher)
|
|
@@ -460,7 +509,7 @@ export class CloakPrivate {
|
|
|
460
509
|
}
|
|
461
510
|
/**
|
|
462
511
|
* Private transfer inside a pool: sender, recipient and amount all stay hidden.
|
|
463
|
-
* `token` = a launch token, or the WHYPE address / hypeMarket.token for HYPE.
|
|
512
|
+
* `token` = a launch token, an asset such as USDC, or the WHYPE address / hypeMarket.token for HYPE.
|
|
464
513
|
*/
|
|
465
514
|
async send(token, to, amount, onStatus = () => { }) {
|
|
466
515
|
const rcpt = parseCloakAddress(to);
|
|
@@ -484,7 +533,7 @@ export class CloakPrivate {
|
|
|
484
533
|
onStatus("Relaying private transfer…");
|
|
485
534
|
return this.submit({ kind: "transact", pool, proof, extData });
|
|
486
535
|
}
|
|
487
|
-
/** Private launch
|
|
536
|
+
/** Private tokens (a launch token, or an asset such as USDC) → any address. */
|
|
488
537
|
async unshieldToken(token, to, amount, onStatus = () => { }) {
|
|
489
538
|
const pool = this.market(token).pool;
|
|
490
539
|
const q = await this.relayFee("transact", pool);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloakely/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
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",
|