@cloak.dev/sdk 0.1.8 → 0.2.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.
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  NATIVE_SOL_MINT,
3
- bigintToBytes32,
3
+ bigintToBytes322 as bigintToBytes32,
4
4
  bigintToHex,
5
- computeCommitment,
6
- computeNullifier,
5
+ computeCommitment2 as computeCommitment,
6
+ computeNullifier2 as computeNullifier,
7
7
  computeSignature,
8
8
  createUtxo,
9
9
  createZeroUtxo,
@@ -11,14 +11,15 @@ import {
11
11
  deriveUtxoKeypairFromSpendKey,
12
12
  deserializeUtxo,
13
13
  generateUtxoKeypair,
14
- hexToBigint,
14
+ hexToBigint2 as hexToBigint,
15
15
  pubkeyToFieldElement,
16
+ pubkeyToFieldLimbs,
16
17
  randomFieldElement,
17
18
  selectUtxos,
18
19
  serializeUtxo,
19
20
  sumUtxoAmounts,
20
21
  utxoEquals
21
- } from "./chunk-2SOX3JNO.js";
22
+ } from "./chunk-YX5SCAMR.js";
22
23
  export {
23
24
  NATIVE_SOL_MINT,
24
25
  bigintToBytes32,
@@ -34,6 +35,7 @@ export {
34
35
  generateUtxoKeypair,
35
36
  hexToBigint,
36
37
  pubkeyToFieldElement,
38
+ pubkeyToFieldLimbs,
37
39
  randomFieldElement,
38
40
  selectUtxos,
39
41
  serializeUtxo,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloak.dev/sdk",
3
- "description": "Shield, send, and swap on Solana privately TypeScript SDK with UTXO-based zero-knowledge transactions",
4
- "version": "0.1.8",
3
+ "description": "Shield, send, and swap on Solana privately \u2014 TypeScript SDK with UTXO-based zero-knowledge transactions",
4
+ "version": "0.2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -22,7 +22,8 @@
22
22
  "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
23
23
  "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
24
24
  "prepare": "npm run build",
25
- "prepublishOnly": "npm run build",
25
+ "prepublishOnly": "npm run build && node scripts/verify-dist-matches-src.mjs",
26
+ "verify:dist": "node scripts/verify-dist-matches-src.mjs",
26
27
  "example:fast-send": "tsx examples/fast-send.ts",
27
28
  "example:fast-usdc-send": "tsx examples/fast-usdc-send.ts",
28
29
  "example:usdc-pool-transfer": "tsx examples/usdc-pool-transfer.ts",
@@ -1,255 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/core/utxo.ts
9
- import { PublicKey } from "@solana/web3.js";
10
- import { buildPoseidon } from "circomlibjs";
11
- import { blake3 } from "@noble/hashes/blake3";
12
- var FIELD_MODULUS = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
13
- var UTXO_KEY_DOMAIN = new TextEncoder().encode("cloak_utxo_priv_v1");
14
- var NATIVE_SOL_MINT = new PublicKey("So11111111111111111111111111111111111111112");
15
- var poseidonInstance = null;
16
- async function getPoseidon() {
17
- if (!poseidonInstance) {
18
- poseidonInstance = await buildPoseidon();
19
- }
20
- return poseidonInstance;
21
- }
22
- function randomFieldElement() {
23
- const bytes = new Uint8Array(32);
24
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
25
- crypto.getRandomValues(bytes);
26
- } else {
27
- const { randomBytes } = __require("crypto");
28
- const nodeBytes = randomBytes(32);
29
- for (let i = 0; i < 32; i++) {
30
- bytes[i] = nodeBytes[i];
31
- }
32
- }
33
- let value = BigInt(0);
34
- for (let i = 0; i < 32; i++) {
35
- value = value << BigInt(8) | BigInt(bytes[i]);
36
- }
37
- return value % (FIELD_MODULUS >> BigInt(4));
38
- }
39
- async function generateUtxoKeypair() {
40
- const poseidon = await getPoseidon();
41
- const privateKey = randomFieldElement();
42
- const publicKeyHash = poseidon([privateKey, BigInt(0)]);
43
- const publicKey = poseidon.F.toObject(publicKeyHash);
44
- return { privateKey, publicKey };
45
- }
46
- async function deriveUtxoKeypairFromSpendKey(skSpend) {
47
- if (!skSpend || !(skSpend instanceof Uint8Array) || skSpend.length !== 32) {
48
- throw new Error("skSpend must be 32 bytes");
49
- }
50
- const preimage = new Uint8Array(UTXO_KEY_DOMAIN.length + skSpend.length);
51
- preimage.set(UTXO_KEY_DOMAIN, 0);
52
- preimage.set(skSpend, UTXO_KEY_DOMAIN.length);
53
- const hash = blake3(preimage);
54
- let value = BigInt(0);
55
- for (let i = 0; i < 32; i++) {
56
- value = value << BigInt(8) | BigInt(hash[i]);
57
- }
58
- const privateKey = value % (FIELD_MODULUS >> BigInt(4));
59
- const publicKey = await derivePublicKey(privateKey);
60
- return { privateKey, publicKey };
61
- }
62
- async function derivePublicKey(privateKey) {
63
- const poseidon = await getPoseidon();
64
- const hash = poseidon([privateKey, BigInt(0)]);
65
- return poseidon.F.toObject(hash);
66
- }
67
- async function createUtxo(amount, keypair, mintAddress = NATIVE_SOL_MINT) {
68
- const blinding = randomFieldElement();
69
- const utxo = {
70
- amount,
71
- keypair,
72
- blinding,
73
- mintAddress
74
- };
75
- utxo.commitment = await computeCommitment(utxo);
76
- return utxo;
77
- }
78
- async function createZeroUtxo(mintAddress = NATIVE_SOL_MINT, salt) {
79
- const poseidon = await getPoseidon();
80
- const effectiveSalt = salt ?? randomFieldElement();
81
- const publicKeyHash = poseidon([effectiveSalt, BigInt(0)]);
82
- const publicKey = poseidon.F.toObject(publicKeyHash);
83
- const keypair = { privateKey: effectiveSalt, publicKey };
84
- const utxo = {
85
- amount: BigInt(0),
86
- keypair,
87
- blinding: BigInt(0),
88
- mintAddress
89
- };
90
- utxo.commitment = await computeCommitment(utxo);
91
- utxo.index = 0;
92
- return utxo;
93
- }
94
- function pubkeyToFieldElement(pubkey) {
95
- const bytes = pubkey.toBytes();
96
- let value = BigInt(0);
97
- for (let i = 0; i < 32; i++) {
98
- value = value << BigInt(8) | BigInt(bytes[i]);
99
- }
100
- return value % FIELD_MODULUS;
101
- }
102
- async function computeCommitment(utxo) {
103
- const poseidon = await getPoseidon();
104
- const mintField = pubkeyToFieldElement(utxo.mintAddress);
105
- const hash = poseidon([
106
- utxo.amount,
107
- utxo.keypair.publicKey,
108
- utxo.blinding,
109
- mintField
110
- ]);
111
- return poseidon.F.toObject(hash);
112
- }
113
- async function computeSignature(privateKey, commitment, pathIndex) {
114
- const poseidon = await getPoseidon();
115
- const hash = poseidon([privateKey, commitment, pathIndex]);
116
- return poseidon.F.toObject(hash);
117
- }
118
- async function computeNullifier(utxo) {
119
- if (utxo.index === void 0) {
120
- throw new Error("UTXO must have an index to compute nullifier");
121
- }
122
- const poseidon = await getPoseidon();
123
- const commitment = utxo.commitment ?? await computeCommitment(utxo);
124
- const pathIndex = BigInt(utxo.index);
125
- const signature = await computeSignature(
126
- utxo.keypair.privateKey,
127
- commitment,
128
- pathIndex
129
- );
130
- const hash = poseidon([commitment, pathIndex, signature]);
131
- return poseidon.F.toObject(hash);
132
- }
133
- function serializeUtxo(utxo) {
134
- const buffer = new ArrayBuffer(128);
135
- const view = new DataView(buffer);
136
- const amountBytes = bigintToBytes(utxo.amount, 8);
137
- for (let i = 0; i < 8; i++) {
138
- view.setUint8(i, amountBytes[i]);
139
- }
140
- const privkeyBytes = bigintToBytes(utxo.keypair.privateKey, 32);
141
- for (let i = 0; i < 32; i++) {
142
- view.setUint8(8 + i, privkeyBytes[i]);
143
- }
144
- const blindingBytes = bigintToBytes(utxo.blinding, 32);
145
- for (let i = 0; i < 32; i++) {
146
- view.setUint8(40 + i, blindingBytes[i]);
147
- }
148
- const mintBytes = utxo.mintAddress.toBytes();
149
- for (let i = 0; i < 32; i++) {
150
- view.setUint8(72 + i, mintBytes[i]);
151
- }
152
- view.setUint32(104, utxo.index ?? 0, true);
153
- return new Uint8Array(buffer);
154
- }
155
- async function deserializeUtxo(bytes) {
156
- const view = new DataView(bytes.buffer, bytes.byteOffset);
157
- const amountBytes = bytes.slice(0, 8);
158
- const amount = bytesToBigint(amountBytes);
159
- const privkeyBytes = bytes.slice(8, 40);
160
- const privateKey = bytesToBigint(privkeyBytes);
161
- const publicKey = await derivePublicKey(privateKey);
162
- const blindingBytes = bytes.slice(40, 72);
163
- const blinding = bytesToBigint(blindingBytes);
164
- const mintBytes = bytes.slice(72, 104);
165
- const mintAddress = new PublicKey(mintBytes);
166
- const index = view.getUint32(104, true);
167
- const utxo = {
168
- amount,
169
- keypair: { privateKey, publicKey },
170
- blinding,
171
- mintAddress,
172
- index: index > 0 ? index : void 0
173
- };
174
- utxo.commitment = await computeCommitment(utxo);
175
- return utxo;
176
- }
177
- function bigintToBytes(value, length) {
178
- const result = new Uint8Array(length);
179
- let remaining = value;
180
- for (let i = 0; i < length; i++) {
181
- result[i] = Number(remaining & BigInt(255));
182
- remaining >>= BigInt(8);
183
- }
184
- return result;
185
- }
186
- function bytesToBigint(bytes) {
187
- let result = BigInt(0);
188
- for (let i = bytes.length - 1; i >= 0; i--) {
189
- result = result << BigInt(8) | BigInt(bytes[i]);
190
- }
191
- return result;
192
- }
193
- function bigintToHex(value) {
194
- return value.toString(16).padStart(64, "0");
195
- }
196
- function hexToBigint(hex) {
197
- const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
198
- return BigInt("0x" + cleanHex);
199
- }
200
- function bigintToBytes32(value) {
201
- const result = new Uint8Array(32);
202
- let remaining = value;
203
- for (let i = 31; i >= 0; i--) {
204
- result[i] = Number(remaining & BigInt(255));
205
- remaining >>= BigInt(8);
206
- }
207
- return result;
208
- }
209
- async function utxoEquals(a, b) {
210
- const commitmentA = a.commitment ?? await computeCommitment(a);
211
- const commitmentB = b.commitment ?? await computeCommitment(b);
212
- return commitmentA === commitmentB;
213
- }
214
- function sumUtxoAmounts(utxos) {
215
- return utxos.reduce((sum, utxo) => sum + utxo.amount, BigInt(0));
216
- }
217
- function selectUtxos(available, targetAmount) {
218
- const sorted = [...available].sort(
219
- (a, b) => Number(b.amount - a.amount)
220
- );
221
- const selected = [];
222
- let total = BigInt(0);
223
- for (const utxo of sorted) {
224
- if (total >= targetAmount) break;
225
- selected.push(utxo);
226
- total += utxo.amount;
227
- }
228
- if (total < targetAmount) {
229
- return null;
230
- }
231
- return selected;
232
- }
233
-
234
- export {
235
- __require,
236
- NATIVE_SOL_MINT,
237
- randomFieldElement,
238
- generateUtxoKeypair,
239
- deriveUtxoKeypairFromSpendKey,
240
- derivePublicKey,
241
- createUtxo,
242
- createZeroUtxo,
243
- pubkeyToFieldElement,
244
- computeCommitment,
245
- computeSignature,
246
- computeNullifier,
247
- serializeUtxo,
248
- deserializeUtxo,
249
- bigintToHex,
250
- hexToBigint,
251
- bigintToBytes32,
252
- utxoEquals,
253
- sumUtxoAmounts,
254
- selectUtxos
255
- };