@veilo/sdk-core 0.3.3 → 0.4.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.
Files changed (195) hide show
  1. package/README.md +42 -3
  2. package/SHIELD_INTEGRATION.md +143 -0
  3. package/config.d.ts +2 -0
  4. package/config.js +4 -0
  5. package/dist/cjs/client.d.ts +5 -5
  6. package/dist/cjs/client.js +79 -42
  7. package/dist/cjs/compactNote.d.ts +107 -0
  8. package/dist/cjs/compactNote.js +167 -0
  9. package/dist/cjs/events.d.ts +1 -1
  10. package/dist/cjs/events.js +2 -2
  11. package/dist/cjs/idl/privacy_pool.d.ts +5 -0
  12. package/dist/cjs/idl/privacy_pool.js +15218 -0
  13. package/dist/cjs/index.d.ts +16 -13
  14. package/dist/cjs/index.js +40 -30
  15. package/dist/cjs/merkle.d.ts +13 -0
  16. package/dist/cjs/merkle.js +31 -8
  17. package/dist/cjs/program.d.ts +11 -0
  18. package/dist/cjs/program.js +26 -3
  19. package/dist/cjs/proof.d.ts +1 -1
  20. package/dist/cjs/proof.js +37 -37
  21. package/dist/cjs/prover.d.ts +1 -1
  22. package/dist/cjs/prover.js +2 -2
  23. package/dist/cjs/random.d.ts +16 -0
  24. package/dist/cjs/random.js +28 -0
  25. package/dist/cjs/relayer.d.ts +27 -4
  26. package/dist/cjs/relayer.js +16 -5
  27. package/dist/cjs/shield/alt.d.ts +87 -0
  28. package/dist/cjs/shield/alt.js +194 -0
  29. package/dist/cjs/shield/computeBudget.d.ts +61 -0
  30. package/dist/cjs/shield/computeBudget.js +64 -0
  31. package/dist/cjs/shield/errors.d.ts +58 -0
  32. package/dist/cjs/shield/errors.js +121 -0
  33. package/dist/cjs/shield/finalize.d.ts +45 -0
  34. package/dist/cjs/shield/finalize.js +119 -0
  35. package/dist/cjs/shield/index.d.ts +35 -0
  36. package/dist/cjs/shield/index.js +68 -0
  37. package/dist/cjs/shield/ix.d.ts +54 -0
  38. package/dist/cjs/shield/ix.js +119 -0
  39. package/dist/cjs/shield/owner.d.ts +36 -0
  40. package/dist/cjs/shield/owner.js +126 -0
  41. package/dist/cjs/shield/ports.d.ts +43 -0
  42. package/dist/cjs/shield/ports.js +153 -0
  43. package/dist/cjs/shield/preflight.d.ts +30 -0
  44. package/dist/cjs/shield/preflight.js +154 -0
  45. package/dist/cjs/shield/shield.d.ts +68 -0
  46. package/dist/cjs/shield/shield.js +499 -0
  47. package/dist/cjs/shield/types.d.ts +202 -0
  48. package/dist/cjs/shield/types.js +2 -0
  49. package/dist/cjs/utxo.d.ts +20 -0
  50. package/dist/cjs/utxo.js +41 -28
  51. package/dist/esm/client.d.ts +407 -0
  52. package/dist/esm/client.js +9 -5
  53. package/dist/esm/compactNote.d.ts +107 -0
  54. package/dist/esm/compactNote.js +156 -0
  55. package/dist/esm/config.d.ts +82 -0
  56. package/dist/esm/events.d.ts +77 -0
  57. package/dist/esm/events.js +1 -1
  58. package/dist/esm/idl/privacy_pool.d.ts +5 -0
  59. package/dist/esm/idl/privacy_pool.js +15216 -0
  60. package/dist/esm/index.d.ts +16 -0
  61. package/dist/esm/index.js +18 -11
  62. package/dist/esm/merkle.d.ts +77 -0
  63. package/dist/esm/merkle.js +23 -1
  64. package/dist/esm/package.json +1 -0
  65. package/dist/esm/poseidon.d.ts +29 -0
  66. package/dist/esm/program.d.ts +37 -0
  67. package/dist/esm/program.js +23 -1
  68. package/dist/esm/proof.d.ts +183 -0
  69. package/dist/esm/proof.js +2 -2
  70. package/dist/esm/prover.d.ts +54 -0
  71. package/dist/esm/prover.js +1 -1
  72. package/dist/esm/random.d.ts +16 -0
  73. package/dist/esm/random.js +21 -0
  74. package/dist/esm/relayer.d.ts +318 -0
  75. package/dist/esm/relayer.js +16 -5
  76. package/dist/esm/retry.d.ts +32 -0
  77. package/dist/esm/shield/alt.d.ts +87 -0
  78. package/dist/esm/shield/alt.js +186 -0
  79. package/dist/esm/shield/computeBudget.d.ts +61 -0
  80. package/dist/esm/shield/computeBudget.js +61 -0
  81. package/dist/esm/shield/errors.d.ts +58 -0
  82. package/dist/esm/shield/errors.js +115 -0
  83. package/dist/esm/shield/finalize.d.ts +45 -0
  84. package/dist/esm/shield/finalize.js +83 -0
  85. package/dist/esm/shield/index.d.ts +35 -0
  86. package/dist/esm/shield/index.js +32 -0
  87. package/dist/esm/shield/ix.d.ts +54 -0
  88. package/dist/esm/shield/ix.js +82 -0
  89. package/dist/esm/shield/owner.d.ts +36 -0
  90. package/dist/esm/shield/owner.js +122 -0
  91. package/dist/esm/shield/ports.d.ts +43 -0
  92. package/dist/esm/shield/ports.js +147 -0
  93. package/dist/esm/shield/preflight.d.ts +30 -0
  94. package/dist/esm/shield/preflight.js +151 -0
  95. package/dist/esm/shield/shield.d.ts +68 -0
  96. package/dist/esm/shield/shield.js +492 -0
  97. package/dist/esm/shield/types.d.ts +202 -0
  98. package/dist/esm/shield/types.js +1 -0
  99. package/dist/esm/utxo.d.ts +235 -0
  100. package/dist/esm/utxo.js +18 -8
  101. package/dist/src/client.d.ts +407 -0
  102. package/dist/src/client.js +951 -0
  103. package/dist/src/compactNote.d.ts +107 -0
  104. package/dist/src/compactNote.js +167 -0
  105. package/dist/src/config.d.ts +82 -0
  106. package/dist/src/config.js +57 -0
  107. package/dist/src/events.d.ts +77 -0
  108. package/dist/src/events.js +167 -0
  109. package/dist/src/idl/privacy_pool.d.ts +5 -0
  110. package/dist/src/idl/privacy_pool.js +15218 -0
  111. package/dist/src/index.d.ts +16 -0
  112. package/dist/src/index.js +67 -0
  113. package/dist/src/merkle.d.ts +77 -0
  114. package/dist/src/merkle.js +156 -0
  115. package/dist/src/poseidon.d.ts +29 -0
  116. package/dist/src/poseidon.js +100 -0
  117. package/dist/src/program.d.ts +37 -0
  118. package/dist/src/program.js +61 -0
  119. package/dist/src/proof.d.ts +183 -0
  120. package/dist/src/proof.js +292 -0
  121. package/dist/src/prover.d.ts +54 -0
  122. package/dist/src/prover.js +112 -0
  123. package/dist/src/random.d.ts +16 -0
  124. package/dist/src/random.js +28 -0
  125. package/dist/src/relayer.d.ts +318 -0
  126. package/dist/src/relayer.js +257 -0
  127. package/dist/src/retry.d.ts +32 -0
  128. package/dist/src/retry.js +75 -0
  129. package/dist/src/shield/alt.d.ts +87 -0
  130. package/dist/src/shield/alt.js +194 -0
  131. package/dist/src/shield/computeBudget.d.ts +61 -0
  132. package/dist/src/shield/computeBudget.js +64 -0
  133. package/dist/src/shield/errors.d.ts +58 -0
  134. package/dist/src/shield/errors.js +121 -0
  135. package/dist/src/shield/finalize.d.ts +45 -0
  136. package/dist/src/shield/finalize.js +119 -0
  137. package/dist/src/shield/index.d.ts +35 -0
  138. package/dist/src/shield/index.js +68 -0
  139. package/dist/src/shield/ix.d.ts +54 -0
  140. package/dist/src/shield/ix.js +119 -0
  141. package/dist/src/shield/owner.d.ts +36 -0
  142. package/dist/src/shield/owner.js +126 -0
  143. package/dist/src/shield/ports.d.ts +43 -0
  144. package/dist/src/shield/ports.js +153 -0
  145. package/dist/src/shield/preflight.d.ts +30 -0
  146. package/dist/src/shield/preflight.js +154 -0
  147. package/dist/src/shield/shield.d.ts +68 -0
  148. package/dist/src/shield/shield.js +499 -0
  149. package/dist/src/shield/types.d.ts +202 -0
  150. package/dist/src/shield/types.js +2 -0
  151. package/dist/src/utxo.d.ts +235 -0
  152. package/dist/src/utxo.js +407 -0
  153. package/dist/tests/compact-note.test.d.ts +1 -0
  154. package/dist/tests/compact-note.test.js +173 -0
  155. package/dist/tests/config.test.d.ts +1 -0
  156. package/dist/tests/config.test.js +102 -0
  157. package/dist/tests/edge-cases.test.d.ts +1 -0
  158. package/dist/tests/edge-cases.test.js +220 -0
  159. package/dist/tests/encryption.test.d.ts +1 -0
  160. package/dist/tests/encryption.test.js +215 -0
  161. package/dist/tests/events.test.d.ts +1 -0
  162. package/dist/tests/events.test.js +78 -0
  163. package/dist/tests/multi-tree.test.d.ts +1 -0
  164. package/dist/tests/multi-tree.test.js +405 -0
  165. package/dist/tests/pda.test.d.ts +1 -0
  166. package/dist/tests/pda.test.js +229 -0
  167. package/dist/tests/poseidon-builder-parity.test.d.ts +1 -0
  168. package/dist/tests/poseidon-builder-parity.test.js +72 -0
  169. package/dist/tests/poseidon.test.d.ts +1 -0
  170. package/dist/tests/poseidon.test.js +142 -0
  171. package/dist/tests/proof.test.d.ts +1 -0
  172. package/dist/tests/proof.test.js +296 -0
  173. package/dist/tests/relayer.test.d.ts +1 -0
  174. package/dist/tests/relayer.test.js +271 -0
  175. package/dist/tests/sdk.integration.test.d.ts +1 -0
  176. package/dist/tests/sdk.integration.test.js +330 -0
  177. package/dist/tests/shield-owner.test.d.ts +1 -0
  178. package/dist/tests/shield-owner.test.js +89 -0
  179. package/dist/tests/shield-preflight.test.d.ts +1 -0
  180. package/dist/tests/shield-preflight.test.js +87 -0
  181. package/dist/tests/shield-realproof.test.d.ts +1 -0
  182. package/dist/tests/shield-realproof.test.js +272 -0
  183. package/dist/tests/shield.test.d.ts +1 -0
  184. package/dist/tests/shield.test.js +403 -0
  185. package/dist/tests/utxo.test.d.ts +1 -0
  186. package/dist/tests/utxo.test.js +140 -0
  187. package/package.json +69 -11
  188. package/poseidon.d.ts +2 -0
  189. package/poseidon.js +4 -0
  190. package/proof.d.ts +2 -0
  191. package/proof.js +4 -0
  192. package/prover.d.ts +2 -0
  193. package/prover.js +4 -0
  194. package/shield.d.ts +2 -0
  195. package/shield.js +4 -0
@@ -0,0 +1,16 @@
1
+ export * from "./client.js";
2
+ export * from "./utxo.js";
3
+ export * from "./config.js";
4
+ export * from "./merkle.js";
5
+ export * from "./proof.js";
6
+ export * from "./events.js";
7
+ export { createVeiloProgram, createReadonlyVeiloProgram, PRIVACY_POOL_IDL, PRIVACY_POOL_PROGRAM_ID, } from "./program.js";
8
+ export * from "./shield/index.js";
9
+ export { createTransactionProver, verifyProof } from "./prover.js";
10
+ export type { CircuitArtifacts } from "./prover.js";
11
+ export * from "./compactNote.js";
12
+ export { randomBytes, randomBytes32 } from "./random.js";
13
+ export * from "./relayer.js";
14
+ export { withRpcRetry, DEFAULT_RPC_RETRY } from "./retry.js";
15
+ export type { RpcRetryPolicy } from "./retry.js";
16
+ export { initPoseidon, getPoseidon, BN254_FR_MODULUS, bytesToBigIntBE, bigIntToBytesBE, frToBigInt, poseidon1, poseidon2, poseidon3, poseidon4, pubkeyToField, } from "./poseidon.js";
package/dist/esm/index.js CHANGED
@@ -1,22 +1,29 @@
1
1
  // Core client functions
2
- export * from "./client";
2
+ export * from "./client.js";
3
3
  // UTXO types and functions (replaces note.ts)
4
- export * from "./utxo";
4
+ export * from "./utxo.js";
5
5
  // Configuration constants and types
6
- export * from "./config";
6
+ export * from "./config.js";
7
7
  // Merkle tree implementation
8
- export * from "./merkle";
8
+ export * from "./merkle.js";
9
9
  // Proof types and helpers
10
- export * from "./proof";
10
+ export * from "./proof.js";
11
11
  // On-chain event scanning and tree reconstruction
12
- export * from "./events";
12
+ export * from "./events.js";
13
13
  // Program factory and IDL
14
- export { createVeiloProgram, PRIVACY_POOL_IDL, PRIVACY_POOL_PROGRAM_ID, } from "./program";
14
+ export { createVeiloProgram, createReadonlyVeiloProgram, PRIVACY_POOL_IDL, PRIVACY_POOL_PROGRAM_ID, } from "./program.js";
15
+ // Wallet-agnostic shielding — build an unsigned deposit for any external wallet
16
+ export * from "./shield/index.js";
15
17
  // Proof generation (requires snarkjs peer dependency)
16
- export { createTransactionProver, verifyProof } from "./prover";
18
+ export { createTransactionProver, verifyProof } from "./prover.js";
19
+ // Compact note ciphers — the on-chain payload that makes notes recoverable
20
+ // from chain data alone, without any relayer involvement.
21
+ export * from "./compactNote.js";
22
+ // Cross-platform CSPRNG (no node:crypto import — safe in browser bundles)
23
+ export { randomBytes, randomBytes32 } from "./random.js";
17
24
  // Relayer API client
18
- export * from "./relayer";
25
+ export * from "./relayer.js";
19
26
  // RPC retry / resilience
20
- export { withRpcRetry, DEFAULT_RPC_RETRY } from "./retry";
27
+ export { withRpcRetry, DEFAULT_RPC_RETRY } from "./retry.js";
21
28
  // Poseidon hash functions
22
- export { initPoseidon, getPoseidon, BN254_FR_MODULUS, bytesToBigIntBE, bigIntToBytesBE, frToBigInt, poseidon1, poseidon2, poseidon3, poseidon4, pubkeyToField, } from "./poseidon";
29
+ export { initPoseidon, getPoseidon, BN254_FR_MODULUS, bytesToBigIntBE, bigIntToBytesBE, frToBigInt, poseidon1, poseidon2, poseidon3, poseidon4, pubkeyToField, } from "./poseidon.js";
@@ -0,0 +1,77 @@
1
+ export type MerklePath = {
2
+ /** Index of the leaf in the tree (0-based) */
3
+ leafIndex: number;
4
+ /** Sibling hashes from leaf level up to (but not including) the root */
5
+ path: Uint8Array[];
6
+ /**
7
+ * 0 = current node is left child, sibling is right
8
+ * 1 = current node is right child, sibling is left
9
+ * (matches your Circom `pathIndices` semantics)
10
+ */
11
+ indices: number[];
12
+ };
13
+ /**
14
+ * Circuit-compatible Merkle path format.
15
+ * The pathIndex is used directly (circuit converts to bits internally via Num2Bits).
16
+ */
17
+ export type CircuitMerklePath = {
18
+ /** Leaf index (circuit converts to bits internally) */
19
+ pathIndex: number;
20
+ /** Sibling hashes as field elements */
21
+ pathElements: bigint[];
22
+ };
23
+ export type Bytes32 = Uint8Array;
24
+ /**
25
+ * Fixed-depth binary Merkle tree over BN254 Fr:
26
+ * - Leaves and internal nodes are 32-byte big-endian Fr elements.
27
+ * - Hash is Poseidon(2)(left, right).
28
+ * - Unfilled leaves use the Poseidon zero chain:
29
+ * zero[0] = 0
30
+ * zero[i+1] = Poseidon(zero[i], zero[i])
31
+ *
32
+ * Depth must match:
33
+ * - Circom WithdrawCircuit(depth)
34
+ * - Rust MERKLE_TREE_HEIGHT
35
+ */
36
+ export declare class MerkleTree {
37
+ readonly depth: number;
38
+ readonly zeroes: Uint8Array[];
39
+ readonly layers: Uint8Array[][];
40
+ nextIndex: number;
41
+ constructor(depth?: number);
42
+ get capacity(): number;
43
+ get root(): Uint8Array;
44
+ /**
45
+ * Insert a leaf and recompute the path up to the root.
46
+ * Returns the leaf index and the new root.
47
+ */
48
+ insert(leaf: Uint8Array): {
49
+ index: number;
50
+ root: Uint8Array;
51
+ };
52
+ /**
53
+ * Return Merkle proof (path + indices) for a given leaf index.
54
+ * This feeds directly into the Circom `MerklePathVerifier(depth)`:
55
+ * - `pathElements[i]` = sibling
56
+ * - `pathIndices[i]` = 0/1 as defined above
57
+ */
58
+ getPath(index: number): MerklePath;
59
+ /**
60
+ * Return Merkle proof in circuit-compatible format.
61
+ * The circuit uses pathIndex directly and converts to bits via Num2Bits(levels).
62
+ */
63
+ getCircuitPath(index: number): CircuitMerklePath;
64
+ }
65
+ /**
66
+ * The Poseidon zero chain: `z[0] = 0`, `z[i+1] = Poseidon(z[i], z[i])`.
67
+ *
68
+ * This is the `zeroes` array a `MerkleTree` builds in its constructor, without
69
+ * the tree. Deposits need a Merkle path for their dummy inputs, but the circuit
70
+ * disables the path check when a input amount is zero (`enabled <== 1 - IsZero(amount)`
71
+ * in transaction.circom), so the values are never constrained — only their
72
+ * count is.
73
+ *
74
+ * Allocating a full depth-22 `MerkleTree` for this costs ~130 MB and several
75
+ * seconds. This costs 22 hashes. Any deposit-shaped transaction should use it.
76
+ */
77
+ export declare function poseidonZeroChain(depth?: number): Uint8Array[];
@@ -1,4 +1,4 @@
1
- import { BN254_FR_MODULUS, bytesToBigIntBE, bigIntToBytesBE, getPoseidon, frToBigInt, } from "./poseidon";
1
+ import { BN254_FR_MODULUS, bytesToBigIntBE, bigIntToBytesBE, getPoseidon, frToBigInt, } from "./poseidon.js";
2
2
  // Poseidon-based hash of two 32-byte field elements.
3
3
  function hashPair(left, right) {
4
4
  if (left.length !== 32 || right.length !== 32) {
@@ -127,3 +127,25 @@ export class MerkleTree {
127
127
  };
128
128
  }
129
129
  }
130
+ /**
131
+ * The Poseidon zero chain: `z[0] = 0`, `z[i+1] = Poseidon(z[i], z[i])`.
132
+ *
133
+ * This is the `zeroes` array a `MerkleTree` builds in its constructor, without
134
+ * the tree. Deposits need a Merkle path for their dummy inputs, but the circuit
135
+ * disables the path check when a input amount is zero (`enabled <== 1 - IsZero(amount)`
136
+ * in transaction.circom), so the values are never constrained — only their
137
+ * count is.
138
+ *
139
+ * Allocating a full depth-22 `MerkleTree` for this costs ~130 MB and several
140
+ * seconds. This costs 22 hashes. Any deposit-shaped transaction should use it.
141
+ */
142
+ export function poseidonZeroChain(depth = 22) {
143
+ const zeroes = [];
144
+ let zero = bigIntToBytesBE(0n);
145
+ zeroes.push(zero);
146
+ for (let level = 1; level <= depth; level++) {
147
+ zero = hashPair(zero, zero);
148
+ zeroes.push(zero);
149
+ }
150
+ return zeroes;
151
+ }
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,29 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ /** Poseidon hash function type from circomlibjs. */
3
+ export type PoseidonFn = ((inputs: bigint[]) => any) & {
4
+ F: {
5
+ toObject: (e: any) => bigint;
6
+ };
7
+ };
8
+ /** Initialize the Poseidon hash instance. Must be called once before using any UTXO/merkle/proof helpers. */
9
+ export declare function initPoseidon(): Promise<void>;
10
+ /** Get the initialized Poseidon instance. Throws if `initPoseidon()` has not been called. */
11
+ export declare function getPoseidon(): PoseidonFn;
12
+ /** The BN254 (alt_bn128) scalar field modulus. All Poseidon outputs are reduced modulo this value. */
13
+ export declare const BN254_FR_MODULUS: bigint;
14
+ /** Convert a big-endian byte array to a bigint. */
15
+ export declare function bytesToBigIntBE(bytes: Uint8Array): bigint;
16
+ /** Convert a bigint to a 32-byte big-endian array. */
17
+ export declare function bigIntToBytesBE(x: bigint): Uint8Array;
18
+ /** Convert ffjavascript field element → bigint safely */
19
+ export declare function frToBigInt(fe: any): bigint;
20
+ /** Poseidon hash with 1 input - used for keypair derivation: pubkey = Poseidon(privateKey) */
21
+ export declare function poseidon1(a: bigint): bigint;
22
+ /** Poseidon hash with 2 inputs */
23
+ export declare function poseidon2(a: bigint, b: bigint): bigint;
24
+ /** Poseidon hash with 3 inputs - used for signature: Poseidon(privateKey, commitment, pathIndex) */
25
+ export declare function poseidon3(a: bigint, b: bigint, c: bigint): bigint;
26
+ /** Poseidon hash with 4 inputs - used for UTXO commitment: Poseidon(amount, pubkey, blinding, mintAddress) */
27
+ export declare function poseidon4(a: bigint, b: bigint, c: bigint, d: bigint): bigint;
28
+ /** Convert a Solana PublicKey to a BN254 field element */
29
+ export declare function pubkeyToField(pubkey: PublicKey): bigint;
@@ -0,0 +1,37 @@
1
+ import { Program, Idl, Wallet } from "@coral-xyz/anchor";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ export declare const PRIVACY_POOL_IDL: Idl;
4
+ /** Deployed program ID extracted from the bundled IDL. */
5
+ export declare const PRIVACY_POOL_PROGRAM_ID: PublicKey;
6
+ /**
7
+ * Create an Anchor `Program` instance for the Veilo Privacy Pool.
8
+ *
9
+ * @param connection Solana RPC connection
10
+ * @param wallet Anchor-compatible wallet (must implement `publicKey` and `signTransaction`)
11
+ * @param opts Optional commitment level (default: "confirmed")
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { createVeiloProgram } from "@veilo/sdk-core";
16
+ * import { Connection } from "@solana/web3.js";
17
+ *
18
+ * const program = createVeiloProgram(
19
+ * new Connection("https://api.devnet.solana.com"),
20
+ * wallet,
21
+ * );
22
+ * ```
23
+ */
24
+ export declare function createVeiloProgram(connection: Connection, wallet: Wallet, opts?: {
25
+ commitment?: "processed" | "confirmed" | "finalized";
26
+ }): Program;
27
+ /**
28
+ * Create a `Program` for reading on-chain accounts, with no wallet.
29
+ *
30
+ * The shield path never signs, so requiring a `Wallet` just to decode a
31
+ * `MerkleTreeAccount` would force integrators to invent a dummy one. This is
32
+ * safe for `program.account.*.fetch` and the coders; anything that would submit
33
+ * a transaction will fail, which is the intent.
34
+ */
35
+ export declare function createReadonlyVeiloProgram(connection: Connection, opts?: {
36
+ commitment?: "processed" | "confirmed" | "finalized";
37
+ }): Program;
@@ -1,6 +1,6 @@
1
1
  import { Program, AnchorProvider } from "@coral-xyz/anchor";
2
2
  import { PublicKey } from "@solana/web3.js";
3
- import IDL_JSON from "./idl/privacy_pool.json";
3
+ import IDL_JSON from "./idl/privacy_pool.js";
4
4
  // Re-export so consumers can access the raw IDL if needed
5
5
  export const PRIVACY_POOL_IDL = IDL_JSON;
6
6
  /** Deployed program ID extracted from the bundled IDL. */
@@ -29,3 +29,25 @@ export function createVeiloProgram(connection, wallet, opts) {
29
29
  });
30
30
  return new Program(PRIVACY_POOL_IDL, provider);
31
31
  }
32
+ /**
33
+ * Create a `Program` for reading on-chain accounts, with no wallet.
34
+ *
35
+ * The shield path never signs, so requiring a `Wallet` just to decode a
36
+ * `MerkleTreeAccount` would force integrators to invent a dummy one. This is
37
+ * safe for `program.account.*.fetch` and the coders; anything that would submit
38
+ * a transaction will fail, which is the intent.
39
+ */
40
+ export function createReadonlyVeiloProgram(connection, opts) {
41
+ const provider = new AnchorProvider(connection,
42
+ // No signing surface: reads only.
43
+ {
44
+ publicKey: PublicKey.default,
45
+ signTransaction: () => {
46
+ throw new Error("createReadonlyVeiloProgram: this program cannot sign");
47
+ },
48
+ signAllTransactions: () => {
49
+ throw new Error("createReadonlyVeiloProgram: this program cannot sign");
50
+ },
51
+ }, { commitment: opts?.commitment ?? "confirmed" });
52
+ return new Program(PRIVACY_POOL_IDL, provider);
53
+ }
@@ -0,0 +1,183 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import { SerializedUTXO, InputUTXO } from "./utxo.js";
3
+ /**
4
+ * External data that gets hashed into ext_data_hash.
5
+ * These are public parameters that affect financial flows.
6
+ */
7
+ export type ExtData = {
8
+ /** Who receives withdrawal (for withdrawals) */
9
+ recipient: PublicKey;
10
+ /** Who submits tx and gets fee */
11
+ relayer: PublicKey;
12
+ /** Fee to relayer in lamports/token units */
13
+ fee: bigint;
14
+ /** Refund to user in lamports/token units (for gas compensation) */
15
+ refund: bigint;
16
+ /** Claimant key committed into the proof */
17
+ claimant: PublicKey;
18
+ };
19
+ /**
20
+ * Transaction circuit inputs (8 public inputs, many private inputs).
21
+ * This structure is used to prepare inputs for the snarkjs prover.
22
+ */
23
+ export type TransactionCircuitInputs = {
24
+ /** Merkle root of UTXO tree */
25
+ root: Uint8Array;
26
+ /** Net deposit/withdrawal amount (positive = deposit, negative = withdrawal) */
27
+ publicAmount: bigint;
28
+ /** Hash of external data (recipient, relayer, fee, refund) */
29
+ extDataHash: Uint8Array;
30
+ /** Token mint address */
31
+ mintAddress: PublicKey;
32
+ /** Nullifiers for the two input UTXOs */
33
+ inputNullifiers: [Uint8Array, Uint8Array];
34
+ /** Commitments for the two output UTXOs */
35
+ outputCommitments: [Uint8Array, Uint8Array];
36
+ inAmount: [bigint, bigint];
37
+ inPubkey: [bigint, bigint];
38
+ inBlinding: [bigint, bigint];
39
+ inPathIndex: [number, number];
40
+ inPathElements: [bigint[], bigint[]];
41
+ inPrivateKey: [bigint, bigint];
42
+ outAmount: [bigint, bigint];
43
+ outPubkey: [bigint, bigint];
44
+ outBlinding: [bigint, bigint];
45
+ };
46
+ /**
47
+ * Proof structure matching the on-chain TransactionProof struct.
48
+ * Total size: 256 bytes (64 + 128 + 64)
49
+ */
50
+ export type TransactionProofStruct = {
51
+ /** G1 point A (64 bytes) */
52
+ proofA: number[];
53
+ /** G2 point B (128 bytes) */
54
+ proofB: number[];
55
+ /** G1 point C (64 bytes) */
56
+ proofC: number[];
57
+ };
58
+ /**
59
+ * Shape of a Groth16 proof produced by snarkjs.
60
+ */
61
+ export type RawProof = {
62
+ pi_a: [string, string, string];
63
+ pi_b: [[string, string], [string, string], [string, string]];
64
+ pi_c: [string, string, string];
65
+ protocol: string;
66
+ curve: string;
67
+ };
68
+ /**
69
+ * Proof builder function type - takes circuit inputs and returns a raw snarkjs proof.
70
+ */
71
+ export type TransactionProofBuilder = (inputs: TransactionCircuitInputs) => Promise<RawProof>;
72
+ /**
73
+ * Compute the external data hash.
74
+ * Matches on-chain computation:
75
+ * hash1 = Poseidon(recipient, relayer)
76
+ * hash2 = Poseidon(fee, refund)
77
+ * extDataHash = Poseidon(hash1, hash2, claimant)
78
+ */
79
+ export declare function computeExtDataHash(extData: ExtData): Uint8Array;
80
+ /**
81
+ * Convert i64 to field element (handles negative via modular arithmetic).
82
+ * For negative values, we add the field modulus to get the equivalent positive representation.
83
+ */
84
+ export declare function i64ToField(value: bigint): bigint;
85
+ /**
86
+ * Prepare transaction circuit inputs from high-level parameters.
87
+ * This converts the SDK types into the format expected by the circuit.
88
+ */
89
+ export declare function prepareTransactionInputs(params: {
90
+ inputUTXOs: [InputUTXO, InputUTXO];
91
+ outputUTXOs: [SerializedUTXO, SerializedUTXO];
92
+ root: Uint8Array;
93
+ publicAmount: bigint;
94
+ extData: ExtData;
95
+ mintAddress: PublicKey;
96
+ }): TransactionCircuitInputs;
97
+ /**
98
+ * Turn a snarkjs Groth16 proof into 256 bytes:
99
+ * A(G1) | B(G2) | C(G1)
100
+ * where:
101
+ * A = (ax, ay) -> 64 bytes
102
+ * B = (bx1, bx0, by1, by0) -> 128 bytes (swapped pairs for alt_bn128)
103
+ * C = (cx, cy) -> 64 bytes
104
+ *
105
+ * Each field element is encoded as 32-byte BE to match the on-chain verifier.
106
+ * We ignore the extra projective/z components snarkjs keeps.
107
+ */
108
+ export declare function packProofToBytes(proof: RawProof): Uint8Array;
109
+ /**
110
+ * Encode a snarkjs proof into the TransactionProofStruct format expected by the on-chain program.
111
+ */
112
+ export declare function encodeSnarkjsProofToTransactionProof(proof: RawProof): TransactionProofStruct;
113
+ /**
114
+ * Convert TransactionCircuitInputs to the format expected by snarkjs.groth16.fullProve().
115
+ * All values are converted to strings (snarkjs expects string inputs for field elements).
116
+ */
117
+ export declare function formatInputsForSnarkjs(inputs: TransactionCircuitInputs): Record<string, any>;
118
+ /**
119
+ * Swap circuit inputs. Matches the signal shape declared by swap.circom's
120
+ * main component (see zk-circuits/swap.circom lines 208-238). Unlike the
121
+ * transaction circuit, the swap circuit distinguishes a "change" output
122
+ * (same mint as source) from a "dest" output (dest mint) and takes a
123
+ * swap-specific params hash and swapAmount alongside the usual inputs.
124
+ */
125
+ export type SwapCircuitInputs = {
126
+ sourceRoot: Uint8Array;
127
+ swapParamsHash: Uint8Array;
128
+ extDataHash: Uint8Array;
129
+ sourceMint: PublicKey;
130
+ destMint: PublicKey;
131
+ inputNullifiers: [Uint8Array, Uint8Array];
132
+ changeCommitment: Uint8Array;
133
+ destCommitment: Uint8Array;
134
+ swapAmount: bigint;
135
+ inAmount: [bigint, bigint];
136
+ inPubkey: [bigint, bigint];
137
+ inBlinding: [bigint, bigint];
138
+ inPathIndex: [number, number];
139
+ inPathElements: [bigint[], bigint[]];
140
+ inPrivateKey: [bigint, bigint];
141
+ changeAmount: bigint;
142
+ changePubkey: bigint;
143
+ changeBlinding: bigint;
144
+ destAmount: bigint;
145
+ destPubkey: bigint;
146
+ destBlinding: bigint;
147
+ minAmountOut: bigint;
148
+ deadline: bigint;
149
+ };
150
+ /**
151
+ * Convert SwapCircuitInputs into the shape expected by
152
+ * snarkjs.groth16.fullProve() for swap.circom. Every value is emitted as a
153
+ * decimal string (or string array) because snarkjs only accepts field
154
+ * elements as strings.
155
+ *
156
+ * Mirrors `generateSwapProof` in
157
+ * relayer-server/src/controllers/swap.helpers.ts so SDK-side swap proofs
158
+ * verify against the same circuit the relayer uses.
159
+ */
160
+ export declare function formatSwapInputsForSnarkjs(inputs: SwapCircuitInputs): Record<string, any>;
161
+ /**
162
+ * Compute the swap params hash that the swap circuit and on-chain program verify.
163
+ * Mirrors relayer-server/src/controllers/swap.helpers.ts `computeSwapParamsHash`.
164
+ *
165
+ * Circuit formula (swap.circom lines 293-307):
166
+ * mintPairHash = Poseidon(sourceMint, destMint)
167
+ * swapTermsHash = Poseidon(minAmountOut, deadline, destAmount)
168
+ * swapParamsHash = Poseidon(mintPairHash, swapTermsHash)
169
+ *
170
+ * @param sourceMint Source pool mint
171
+ * @param destMint Destination pool mint
172
+ * @param minAmountOut Minimum accepted output amount (slippage protected)
173
+ * @param deadline Unix timestamp deadline (i64, 0 = no deadline)
174
+ * @param destAmount Actual amount committed to destination UTXO (≥ minAmountOut -
175
+ * relayerFee). If omitted, defaults to minAmountOut.
176
+ */
177
+ export declare function computeSwapParamsHash(sourceMint: PublicKey, destMint: PublicKey, minAmountOut: bigint, deadline: bigint, destAmount?: bigint): Uint8Array;
178
+ /**
179
+ * Compute the swap data hash committed on-chain for Jupiter instruction integrity.
180
+ * SHA-256 of the raw Jupiter swap instruction data bytes.
181
+ * Mirrors relayer-server/src/controllers/swap.helpers.ts `computeSwapDataHash`.
182
+ */
183
+ export declare function computeSwapDataHash(swapData: Uint8Array | Buffer): Uint8Array;
package/dist/esm/proof.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { sha256 } from "@noble/hashes/sha256";
2
- import { BN254_FR_MODULUS, bigIntToBytesBE, bytesToBigIntBE, poseidon2, poseidon3, pubkeyToField, } from "./poseidon";
3
- import { deriveNullifier } from "./utxo";
2
+ import { BN254_FR_MODULUS, bigIntToBytesBE, bytesToBigIntBE, poseidon2, poseidon3, pubkeyToField, } from "./poseidon.js";
3
+ import { deriveNullifier } from "./utxo.js";
4
4
  // -----------------------------------------------------------------------------
5
5
  // ExtData Hash Computation
6
6
  // -----------------------------------------------------------------------------
@@ -0,0 +1,54 @@
1
+ import { TransactionProofBuilder, RawProof } from "./proof.js";
2
+ /**
3
+ * Circuit artifact paths required by snarkjs.
4
+ *
5
+ * These files are large (10-100 MB) and should NOT be bundled in npm.
6
+ * Host them on GitHub Releases, IPFS, or a CDN and download at runtime.
7
+ *
8
+ * For Node.js: pass file system paths (e.g. "./circuits/transaction.wasm").
9
+ * For browsers: pass Uint8Array buffers or URLs that fetch returns as ArrayBuffer.
10
+ */
11
+ export interface CircuitArtifacts {
12
+ /** Path or buffer for the compiled WASM witness generator */
13
+ wasmPath: string | Uint8Array;
14
+ /** Path or buffer for the Groth16 proving key (.zkey) */
15
+ zkeyPath: string | Uint8Array;
16
+ }
17
+ /**
18
+ * Create a proof builder function for the transaction circuit.
19
+ *
20
+ * Uses dynamic `import("snarkjs")` so the dependency is only loaded when
21
+ * proof generation is actually called. Install snarkjs as a peer dependency:
22
+ *
23
+ * ```
24
+ * npm install snarkjs
25
+ * ```
26
+ *
27
+ * @param artifacts Paths or buffers to the circuit WASM and zkey files
28
+ * @returns A `TransactionProofBuilder` callback compatible with the SDK's client functions
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { createTransactionProver } from "@veilo/sdk-core";
33
+ *
34
+ * const prover = createTransactionProver({
35
+ * wasmPath: "./circuits/transaction.wasm",
36
+ * zkeyPath: "./circuits/transaction_final.zkey",
37
+ * });
38
+ *
39
+ * // Pass to SDK functions that accept a TransactionProofBuilder
40
+ * const proof = await prover(circuitInputs);
41
+ * ```
42
+ */
43
+ export declare function createTransactionProver(artifacts: CircuitArtifacts): TransactionProofBuilder;
44
+ /**
45
+ * Verify a Groth16 proof against public signals and a verification key.
46
+ *
47
+ * Useful for local verification before submitting to the relayer.
48
+ *
49
+ * @param proof The raw snarkjs proof
50
+ * @param publicSignals Array of public signal strings
51
+ * @param vkeyPath Path to the verification key JSON file, or the parsed JSON object
52
+ * @returns true if the proof is valid
53
+ */
54
+ export declare function verifyProof(proof: RawProof, publicSignals: string[], vkey: string | object): Promise<boolean>;
@@ -1,4 +1,4 @@
1
- import { formatInputsForSnarkjs, } from "./proof";
1
+ import { formatInputsForSnarkjs, } from "./proof.js";
2
2
  /** Lazy-load snarkjs — works in both CJS and ESM contexts. */
3
3
  async function loadSnarkjs() {
4
4
  try {
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Cross-platform CSPRNG.
3
+ *
4
+ * Deliberately backed by `nacl.randomBytes` rather than Node's `crypto.randomBytes`:
5
+ * tweetnacl resolves to `crypto.getRandomValues` in browsers and to Node's CSPRNG
6
+ * under Node, so this module carries no `node:crypto` import. That matters because
7
+ * every deposit path reaches this code via `createUTXO`/`generateKeypair`, and a
8
+ * bare `import { randomBytes } from "crypto"` throws at bundle time in browser
9
+ * builds that have no Node polyfill.
10
+ *
11
+ * tweetnacl is already a hard dependency, so this adds no install weight.
12
+ */
13
+ /** `length` cryptographically-secure random bytes. */
14
+ export declare function randomBytes(length: number): Uint8Array;
15
+ /** 32 cryptographically-secure random bytes — the common case for blindings and seeds. */
16
+ export declare function randomBytes32(): Uint8Array;
@@ -0,0 +1,21 @@
1
+ import nacl from "tweetnacl";
2
+ /**
3
+ * Cross-platform CSPRNG.
4
+ *
5
+ * Deliberately backed by `nacl.randomBytes` rather than Node's `crypto.randomBytes`:
6
+ * tweetnacl resolves to `crypto.getRandomValues` in browsers and to Node's CSPRNG
7
+ * under Node, so this module carries no `node:crypto` import. That matters because
8
+ * every deposit path reaches this code via `createUTXO`/`generateKeypair`, and a
9
+ * bare `import { randomBytes } from "crypto"` throws at bundle time in browser
10
+ * builds that have no Node polyfill.
11
+ *
12
+ * tweetnacl is already a hard dependency, so this adds no install weight.
13
+ */
14
+ /** `length` cryptographically-secure random bytes. */
15
+ export function randomBytes(length) {
16
+ return nacl.randomBytes(length);
17
+ }
18
+ /** 32 cryptographically-secure random bytes — the common case for blindings and seeds. */
19
+ export function randomBytes32() {
20
+ return nacl.randomBytes(32);
21
+ }