@veilo/sdk-core 0.4.0 → 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/LICENSE +15 -0
- package/README.md +286 -1298
- package/dist/cjs/accounts/admin.d.ts +84 -0
- package/dist/cjs/accounts/admin.js +208 -0
- package/dist/cjs/accounts/errors.d.ts +6 -0
- package/dist/cjs/accounts/errors.js +98 -0
- package/dist/cjs/accounts/index.d.ts +4 -0
- package/dist/cjs/accounts/index.js +20 -0
- package/dist/cjs/accounts/pdas.d.ts +23 -0
- package/dist/cjs/accounts/pdas.js +44 -0
- package/dist/cjs/accounts/queries.d.ts +41 -0
- package/dist/cjs/accounts/queries.js +95 -0
- package/dist/cjs/client.d.ts +2 -407
- package/dist/cjs/client.js +6 -938
- package/dist/cjs/cloak/client.d.ts +28 -0
- package/dist/cjs/cloak/client.js +68 -0
- package/dist/cjs/cloak/errors.d.ts +13 -0
- package/dist/cjs/cloak/errors.js +25 -0
- package/dist/cjs/cloak/helpers.d.ts +6 -0
- package/dist/cjs/cloak/helpers.js +35 -0
- package/dist/cjs/cloak/index.d.ts +6 -0
- package/dist/cjs/cloak/index.js +24 -0
- package/dist/cjs/cloak/polling.d.ts +7 -0
- package/dist/cjs/cloak/polling.js +66 -0
- package/dist/cjs/cloak/transport.d.ts +15 -0
- package/dist/cjs/cloak/transport.js +119 -0
- package/dist/cjs/cloak/types.d.ts +188 -0
- package/dist/cjs/cloak/types.js +5 -0
- package/dist/cjs/cloak.d.ts +1 -0
- package/dist/cjs/cloak.js +18 -0
- package/dist/cjs/compactNote.d.ts +21 -0
- package/dist/cjs/compactNote.js +31 -7
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/notes/encryption.d.ts +41 -0
- package/dist/cjs/notes/encryption.js +75 -0
- package/dist/cjs/notes/index.d.ts +5 -0
- package/dist/cjs/notes/index.js +21 -0
- package/dist/cjs/notes/mailbox.d.ts +70 -0
- package/dist/cjs/notes/mailbox.js +164 -0
- package/dist/cjs/notes/model.d.ts +91 -0
- package/dist/cjs/notes/model.js +109 -0
- package/dist/cjs/notes/nullifier.d.ts +27 -0
- package/dist/cjs/notes/nullifier.js +45 -0
- package/dist/cjs/notes/recovery.d.ts +10 -0
- package/dist/cjs/notes/recovery.js +31 -0
- package/dist/cjs/proof.d.ts +1 -183
- package/dist/cjs/proof.js +16 -290
- package/dist/cjs/proofs/encoding.d.ts +17 -0
- package/dist/cjs/proofs/encoding.js +72 -0
- package/dist/cjs/proofs/formatting.d.ts +6 -0
- package/dist/cjs/proofs/formatting.js +34 -0
- package/dist/cjs/proofs/index.d.ts +5 -0
- package/dist/cjs/proofs/index.js +21 -0
- package/dist/cjs/proofs/swap.d.ts +87 -0
- package/dist/cjs/proofs/swap.js +144 -0
- package/dist/cjs/proofs/transaction.d.ts +28 -0
- package/dist/cjs/proofs/transaction.js +110 -0
- package/dist/cjs/proofs/types.d.ts +70 -0
- package/dist/cjs/prover.d.ts +4 -1
- package/dist/cjs/prover.js +12 -2
- package/dist/cjs/relayer/client.d.ts +61 -0
- package/dist/cjs/relayer/client.js +151 -0
- package/dist/cjs/relayer/crypto.d.ts +5 -0
- package/dist/cjs/relayer/crypto.js +26 -0
- package/dist/cjs/relayer/encoding.d.ts +2 -0
- package/dist/cjs/relayer/encoding.js +23 -0
- package/dist/cjs/relayer/errors.d.ts +7 -0
- package/dist/cjs/relayer/errors.js +17 -0
- package/dist/cjs/relayer/index.d.ts +3 -0
- package/dist/cjs/relayer/index.js +19 -0
- package/dist/cjs/relayer/transport.d.ts +17 -0
- package/dist/cjs/relayer/transport.js +63 -0
- package/dist/{src/relayer.d.ts → cjs/relayer/types.d.ts} +44 -86
- package/dist/cjs/relayer/types.js +5 -0
- package/dist/cjs/relayer.d.ts +1 -318
- package/dist/cjs/relayer.js +15 -254
- package/dist/cjs/shield/alt.js +8 -8
- package/dist/cjs/shield/errors.js +2 -2
- package/dist/cjs/shield/finalize.js +2 -2
- package/dist/cjs/shield/ix.d.ts +1 -1
- package/dist/cjs/shield/owner.js +9 -8
- package/dist/cjs/shield/ports.js +3 -3
- package/dist/cjs/shield/preflight.js +3 -3
- package/dist/cjs/shield/shield.js +20 -19
- package/dist/cjs/shield/types.d.ts +1 -1
- package/dist/cjs/transactions/deposit.d.ts +94 -0
- package/dist/cjs/transactions/deposit.js +234 -0
- package/dist/cjs/transactions/index.d.ts +7 -0
- package/dist/cjs/transactions/index.js +26 -0
- package/dist/cjs/transactions/swap.d.ts +71 -0
- package/dist/cjs/transactions/swap.js +184 -0
- package/dist/cjs/transactions/transact.d.ts +34 -0
- package/dist/cjs/transactions/transact.js +146 -0
- package/dist/cjs/transactions/transfer.d.ts +51 -0
- package/dist/cjs/transactions/transfer.js +106 -0
- package/dist/cjs/transactions/withdraw.d.ts +52 -0
- package/dist/cjs/transactions/withdraw.js +104 -0
- package/dist/cjs/utxo.d.ts +1 -235
- package/dist/cjs/utxo.js +15 -404
- package/dist/esm/accounts/admin.d.ts +84 -0
- package/dist/esm/accounts/admin.js +165 -0
- package/dist/esm/accounts/errors.d.ts +6 -0
- package/dist/esm/accounts/errors.js +95 -0
- package/dist/esm/accounts/index.d.ts +4 -0
- package/dist/esm/accounts/index.js +4 -0
- package/dist/esm/accounts/pdas.d.ts +23 -0
- package/dist/esm/accounts/pdas.js +38 -0
- package/dist/esm/accounts/queries.d.ts +41 -0
- package/dist/esm/accounts/queries.js +88 -0
- package/dist/esm/client.d.ts +2 -407
- package/dist/esm/client.js +3 -891
- package/dist/esm/cloak/client.d.ts +28 -0
- package/dist/esm/cloak/client.js +64 -0
- package/dist/esm/cloak/errors.d.ts +13 -0
- package/dist/esm/cloak/errors.js +21 -0
- package/dist/esm/cloak/helpers.d.ts +6 -0
- package/dist/esm/cloak/helpers.js +31 -0
- package/dist/esm/cloak/index.d.ts +6 -0
- package/dist/esm/cloak/index.js +6 -0
- package/dist/esm/cloak/polling.d.ts +7 -0
- package/dist/esm/cloak/polling.js +63 -0
- package/dist/esm/cloak/transport.d.ts +15 -0
- package/dist/esm/cloak/transport.js +115 -0
- package/dist/esm/cloak/types.d.ts +188 -0
- package/dist/esm/cloak/types.js +4 -0
- package/dist/esm/cloak.d.ts +1 -0
- package/dist/esm/cloak.js +2 -0
- package/dist/esm/compactNote.d.ts +21 -0
- package/dist/esm/compactNote.js +24 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/notes/encryption.d.ts +41 -0
- package/dist/esm/notes/encryption.js +67 -0
- package/dist/esm/notes/index.d.ts +5 -0
- package/dist/esm/notes/index.js +5 -0
- package/dist/esm/notes/mailbox.d.ts +70 -0
- package/dist/esm/notes/mailbox.js +154 -0
- package/dist/esm/notes/model.d.ts +91 -0
- package/dist/esm/notes/model.js +99 -0
- package/dist/esm/notes/nullifier.d.ts +27 -0
- package/dist/esm/notes/nullifier.js +40 -0
- package/dist/esm/notes/recovery.d.ts +10 -0
- package/dist/esm/notes/recovery.js +28 -0
- package/dist/esm/proof.d.ts +1 -183
- package/dist/esm/proof.js +2 -281
- package/dist/esm/proofs/encoding.d.ts +17 -0
- package/dist/esm/proofs/encoding.js +68 -0
- package/dist/esm/proofs/formatting.d.ts +6 -0
- package/dist/esm/proofs/formatting.js +31 -0
- package/dist/esm/proofs/index.d.ts +5 -0
- package/dist/esm/proofs/index.js +5 -0
- package/dist/esm/proofs/swap.d.ts +87 -0
- package/dist/esm/proofs/swap.js +138 -0
- package/dist/esm/proofs/transaction.d.ts +28 -0
- package/dist/esm/proofs/transaction.js +105 -0
- package/dist/esm/proofs/types.d.ts +70 -0
- package/dist/esm/proofs/types.js +1 -0
- package/dist/esm/prover.d.ts +4 -1
- package/dist/esm/prover.js +10 -1
- package/dist/esm/relayer/client.d.ts +61 -0
- package/dist/esm/relayer/client.js +144 -0
- package/dist/esm/relayer/crypto.d.ts +5 -0
- package/dist/esm/relayer/crypto.js +20 -0
- package/dist/esm/relayer/encoding.d.ts +2 -0
- package/dist/esm/relayer/encoding.js +19 -0
- package/dist/esm/relayer/errors.d.ts +7 -0
- package/dist/esm/relayer/errors.js +13 -0
- package/dist/esm/relayer/index.d.ts +3 -0
- package/dist/esm/relayer/index.js +3 -0
- package/dist/esm/relayer/transport.d.ts +17 -0
- package/dist/esm/relayer/transport.js +59 -0
- package/dist/esm/relayer/types.d.ts +276 -0
- package/dist/esm/relayer/types.js +4 -0
- package/dist/esm/relayer.d.ts +1 -318
- package/dist/esm/relayer.js +2 -249
- package/dist/esm/shield/alt.js +1 -1
- package/dist/esm/shield/errors.js +1 -1
- package/dist/esm/shield/finalize.js +1 -1
- package/dist/esm/shield/ix.d.ts +1 -1
- package/dist/esm/shield/owner.js +2 -1
- package/dist/esm/shield/ports.js +1 -1
- package/dist/esm/shield/preflight.js +1 -1
- package/dist/esm/shield/shield.js +4 -3
- package/dist/esm/shield/types.d.ts +1 -1
- package/dist/esm/transactions/deposit.d.ts +94 -0
- package/dist/esm/transactions/deposit.js +198 -0
- package/dist/esm/transactions/index.d.ts +7 -0
- package/dist/esm/transactions/index.js +7 -0
- package/dist/esm/transactions/swap.d.ts +71 -0
- package/dist/esm/transactions/swap.js +144 -0
- package/dist/esm/transactions/transact.d.ts +34 -0
- package/dist/esm/transactions/transact.js +110 -0
- package/dist/esm/transactions/transfer.d.ts +51 -0
- package/dist/esm/transactions/transfer.js +103 -0
- package/dist/esm/transactions/withdraw.d.ts +52 -0
- package/dist/esm/transactions/withdraw.js +101 -0
- package/dist/esm/utxo.d.ts +1 -235
- package/dist/esm/utxo.js +2 -382
- package/package.json +54 -16
- package/SHIELD_INTEGRATION.md +0 -143
- package/config.d.ts +0 -2
- package/config.js +0 -4
- package/dist/src/client.d.ts +0 -407
- package/dist/src/client.js +0 -951
- package/dist/src/compactNote.d.ts +0 -107
- package/dist/src/compactNote.js +0 -167
- package/dist/src/config.d.ts +0 -82
- package/dist/src/config.js +0 -57
- package/dist/src/events.d.ts +0 -77
- package/dist/src/events.js +0 -167
- package/dist/src/idl/privacy_pool.d.ts +0 -5
- package/dist/src/idl/privacy_pool.js +0 -15218
- package/dist/src/index.d.ts +0 -16
- package/dist/src/index.js +0 -67
- package/dist/src/merkle.d.ts +0 -77
- package/dist/src/merkle.js +0 -156
- package/dist/src/poseidon.d.ts +0 -29
- package/dist/src/poseidon.js +0 -100
- package/dist/src/program.d.ts +0 -37
- package/dist/src/program.js +0 -61
- package/dist/src/proof.d.ts +0 -183
- package/dist/src/proof.js +0 -292
- package/dist/src/prover.d.ts +0 -54
- package/dist/src/prover.js +0 -112
- package/dist/src/random.d.ts +0 -16
- package/dist/src/random.js +0 -28
- package/dist/src/relayer.js +0 -257
- package/dist/src/retry.d.ts +0 -32
- package/dist/src/retry.js +0 -75
- package/dist/src/shield/alt.d.ts +0 -87
- package/dist/src/shield/alt.js +0 -194
- package/dist/src/shield/computeBudget.d.ts +0 -61
- package/dist/src/shield/computeBudget.js +0 -64
- package/dist/src/shield/errors.d.ts +0 -58
- package/dist/src/shield/errors.js +0 -121
- package/dist/src/shield/finalize.d.ts +0 -45
- package/dist/src/shield/finalize.js +0 -119
- package/dist/src/shield/index.d.ts +0 -35
- package/dist/src/shield/index.js +0 -68
- package/dist/src/shield/ix.d.ts +0 -54
- package/dist/src/shield/ix.js +0 -119
- package/dist/src/shield/owner.d.ts +0 -36
- package/dist/src/shield/owner.js +0 -126
- package/dist/src/shield/ports.d.ts +0 -43
- package/dist/src/shield/ports.js +0 -153
- package/dist/src/shield/preflight.d.ts +0 -30
- package/dist/src/shield/preflight.js +0 -154
- package/dist/src/shield/shield.d.ts +0 -68
- package/dist/src/shield/shield.js +0 -499
- package/dist/src/shield/types.d.ts +0 -202
- package/dist/src/utxo.d.ts +0 -235
- package/dist/src/utxo.js +0 -407
- package/dist/tests/compact-note.test.d.ts +0 -1
- package/dist/tests/compact-note.test.js +0 -173
- package/dist/tests/config.test.d.ts +0 -1
- package/dist/tests/config.test.js +0 -102
- package/dist/tests/edge-cases.test.d.ts +0 -1
- package/dist/tests/edge-cases.test.js +0 -220
- package/dist/tests/encryption.test.d.ts +0 -1
- package/dist/tests/encryption.test.js +0 -215
- package/dist/tests/events.test.d.ts +0 -1
- package/dist/tests/events.test.js +0 -78
- package/dist/tests/multi-tree.test.d.ts +0 -1
- package/dist/tests/multi-tree.test.js +0 -405
- package/dist/tests/pda.test.d.ts +0 -1
- package/dist/tests/pda.test.js +0 -229
- package/dist/tests/poseidon-builder-parity.test.d.ts +0 -1
- package/dist/tests/poseidon-builder-parity.test.js +0 -72
- package/dist/tests/poseidon.test.d.ts +0 -1
- package/dist/tests/poseidon.test.js +0 -142
- package/dist/tests/proof.test.d.ts +0 -1
- package/dist/tests/proof.test.js +0 -296
- package/dist/tests/relayer.test.d.ts +0 -1
- package/dist/tests/relayer.test.js +0 -271
- package/dist/tests/sdk.integration.test.d.ts +0 -1
- package/dist/tests/sdk.integration.test.js +0 -330
- package/dist/tests/shield-owner.test.d.ts +0 -1
- package/dist/tests/shield-owner.test.js +0 -89
- package/dist/tests/shield-preflight.test.d.ts +0 -1
- package/dist/tests/shield-preflight.test.js +0 -87
- package/dist/tests/shield-realproof.test.d.ts +0 -1
- package/dist/tests/shield-realproof.test.js +0 -272
- package/dist/tests/shield.test.d.ts +0 -1
- package/dist/tests/shield.test.js +0 -403
- package/dist/tests/utxo.test.d.ts +0 -1
- package/dist/tests/utxo.test.js +0 -140
- package/poseidon.d.ts +0 -2
- package/poseidon.js +0 -4
- package/proof.d.ts +0 -2
- package/proof.js +0 -4
- package/prover.d.ts +0 -2
- package/prover.js +0 -4
- package/shield.d.ts +0 -2
- package/shield.js +0 -4
- /package/dist/{src/shield → cjs/proofs}/types.js +0 -0
package/README.md
CHANGED
|
@@ -1,1463 +1,451 @@
|
|
|
1
1
|
# @veilo/sdk-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Build private payments and swaps on Solana with Veilo.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The SDK gives TypeScript applications a safe, typed way to:
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- **Note Encryption**: NaCl-based encrypted UTXO notes and blind mailbox delivery
|
|
12
|
-
- **Event Scanning**: Reconstruct Merkle trees from on-chain events
|
|
13
|
-
- **Poseidon Hashing**: BN254-curve compatible hashing using circomlibjs
|
|
14
|
-
- **Relayer Support**: Built-in relayer infrastructure for private withdrawals and swaps
|
|
7
|
+
- shield SOL or SPL tokens into Veilo;
|
|
8
|
+
- withdraw, privately transfer, or privately swap shielded funds;
|
|
9
|
+
- work with Veilo's relayer without handling its encryption protocol yourself;
|
|
10
|
+
- add partner-powered private sends and swaps through the Cloak API.
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
> Proofs are generated off-chain and verified on-chain using Groth16.
|
|
12
|
+
It works with both ESM and CommonJS and includes TypeScript declarations.
|
|
18
13
|
|
|
19
|
-
|
|
14
|
+
> **Project status:** Active development. Test integrations on Devnet before using
|
|
15
|
+
> them with real funds.
|
|
20
16
|
|
|
21
|
-
##
|
|
17
|
+
## Install
|
|
22
18
|
|
|
23
19
|
```bash
|
|
24
20
|
npm install @veilo/sdk-core
|
|
25
21
|
```
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## 2. Prerequisites
|
|
30
|
-
|
|
31
|
-
- A running Solana validator (localnet/devnet/mainnet)
|
|
32
|
-
- The `privacy-pool` program deployed to the network
|
|
33
|
-
- A funded keypair
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
export ANCHOR_PROVIDER_URL=https://api.devnet.solana.com
|
|
37
|
-
export ANCHOR_WALLET=$HOME/.config/solana/id.json
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 3. Build
|
|
23
|
+
Install `snarkjs` only if your application generates proofs locally:
|
|
43
24
|
|
|
44
25
|
```bash
|
|
45
|
-
npm
|
|
26
|
+
npm install snarkjs
|
|
46
27
|
```
|
|
47
28
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
## 4. SDK API
|
|
51
|
-
|
|
52
|
-
### 4.1 PDA Helpers
|
|
53
|
-
|
|
54
|
-
```ts
|
|
55
|
-
import {
|
|
56
|
-
getPoolPdas,
|
|
57
|
-
getNoteTreePda,
|
|
58
|
-
getGlobalConfigPda,
|
|
59
|
-
getNullifierMarkerPda,
|
|
60
|
-
getSwapExecutorPda,
|
|
61
|
-
} from "@veilo/sdk-core";
|
|
62
|
-
import { PublicKey } from "@solana/web3.js";
|
|
63
|
-
|
|
64
|
-
const programId = new PublicKey(
|
|
65
|
-
"YourProgram1111111111111111111111111111111111",
|
|
66
|
-
);
|
|
67
|
-
const mintAddress = new PublicKey(
|
|
68
|
-
"So11111111111111111111111111111111111111112",
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
// Pool PDAs (config, vault, nullifiers)
|
|
72
|
-
const { config, vault, nullifiers } = getPoolPdas(programId, mintAddress);
|
|
29
|
+
You will also need:
|
|
73
30
|
|
|
74
|
-
|
|
75
|
-
|
|
31
|
+
- a Solana RPC connection;
|
|
32
|
+
- a connected wallet when a user must sign;
|
|
33
|
+
- the Veilo circuit `.wasm` and `.zkey` files for local proof generation;
|
|
34
|
+
- a Veilo-issued API key for partner or relayer endpoints that require one.
|
|
76
35
|
|
|
77
|
-
|
|
78
|
-
const globalConfig = getGlobalConfigPda(programId);
|
|
79
|
-
|
|
80
|
-
// Nullifier marker PDA (prevents double-spend)
|
|
81
|
-
const nullifier = new Uint8Array(32);
|
|
82
|
-
const marker = getNullifierMarkerPda(programId, mintAddress, nullifier);
|
|
83
|
-
|
|
84
|
-
// Swap executor PDA (for cross-pool swaps)
|
|
85
|
-
const relayerPubkey = new PublicKey("...");
|
|
86
|
-
const executor = getSwapExecutorPda(
|
|
87
|
-
programId,
|
|
88
|
-
sourceMint,
|
|
89
|
-
destMint,
|
|
90
|
-
inputNullifier0, // Uint8Array[32]
|
|
91
|
-
relayerPubkey,
|
|
92
|
-
);
|
|
93
|
-
```
|
|
36
|
+
## Choose an integration
|
|
94
37
|
|
|
95
|
-
|
|
38
|
+
| What you want to build | Start with | Who signs? |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| Let any wallet shield funds into Veilo | `shield()` | The user's wallet |
|
|
41
|
+
| Add private transfers or swaps to a partner app | `VeiloCloakClient` | The user's wallet |
|
|
42
|
+
| Build a full Veilo wallet experience | `VeiloRelayerClient` | The relayer for private spends |
|
|
43
|
+
| Manage proofs, notes, trees, and transactions yourself | Transaction helpers | Your application or relayer |
|
|
96
44
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| Config | `["privacy_config_v3", mint]` |
|
|
100
|
-
| Vault | `["privacy_vault_v3", mint]` |
|
|
101
|
-
| Note Tree | `["privacy_note_tree_v3", mint, tree_id]` |
|
|
102
|
-
| Nullifiers | `["privacy_nullifiers_v3", mint]` |
|
|
103
|
-
| Nullifier Marker | `["nullifier_v3", mint, nullifier]` |
|
|
104
|
-
| Global Config | `["global_config_v1"]` |
|
|
105
|
-
| Swap Executor | `["swap_executor_v1", source_mint, dest_mint, nullifier0, relayer]` |
|
|
45
|
+
For most third-party deposit integrations, `shield()` is the best starting
|
|
46
|
+
point. For a managed private send or swap flow, use Cloak.
|
|
106
47
|
|
|
107
|
-
|
|
48
|
+
## Quick start: shield funds
|
|
108
49
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
import {
|
|
113
|
-
initializeGlobalConfig,
|
|
114
|
-
initializePool,
|
|
115
|
-
updatePoolConfig,
|
|
116
|
-
addMerkleTree,
|
|
117
|
-
getPoolConfig,
|
|
118
|
-
updateGlobalConfig,
|
|
119
|
-
} from "@veilo/sdk-core";
|
|
120
|
-
import { NATIVE_SOL_MINT, sol } from "@veilo/sdk-core/config";
|
|
121
|
-
|
|
122
|
-
// Initialize global config (once per program)
|
|
123
|
-
await initializeGlobalConfig({ program, admin: adminKeypair });
|
|
124
|
-
|
|
125
|
-
// Update global config
|
|
126
|
-
await updateGlobalConfig({
|
|
127
|
-
program,
|
|
128
|
-
admin: adminKeypair,
|
|
129
|
-
newAdmin: newAdminPubkey, // optional
|
|
130
|
-
paused: false, // optional
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
// Initialize a pool for native SOL
|
|
134
|
-
await initializePool({
|
|
135
|
-
program,
|
|
136
|
-
payer: adminKeypair,
|
|
137
|
-
admin: adminKeypair,
|
|
138
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
139
|
-
minDepositAmount: sol(0.1),
|
|
140
|
-
maxDepositAmount: sol(100),
|
|
141
|
-
minWithdrawAmount: sol(0.1),
|
|
142
|
-
maxWithdrawAmount: sol(100),
|
|
143
|
-
feeBps: 50, // 0.5%
|
|
144
|
-
feeErrorMarginBps: 10, // 0.1% margin
|
|
145
|
-
minWithdrawalFee: 1_000_000n,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// Add Merkle tree (tree ID 0)
|
|
149
|
-
await addMerkleTree({
|
|
150
|
-
program,
|
|
151
|
-
payer: adminKeypair,
|
|
152
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
153
|
-
treeId: 0,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// Update pool fee
|
|
157
|
-
await updatePoolConfig({
|
|
158
|
-
program,
|
|
159
|
-
admin: adminKeypair,
|
|
160
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
161
|
-
feeBps: 30,
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// Read pool configuration
|
|
165
|
-
const poolConfig = await getPoolConfig(program, NATIVE_SOL_MINT);
|
|
166
|
-
console.log("TVL:", poolConfig.totalTvl, " Fee:", poolConfig.feeBps, "bps");
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
### 4.3 On-Chain Account Queries
|
|
172
|
-
|
|
173
|
-
```ts
|
|
174
|
-
import {
|
|
175
|
-
fetchPoolConfig,
|
|
176
|
-
checkNullifierSpent,
|
|
177
|
-
getTreeInfo,
|
|
178
|
-
getAllTreeInfo,
|
|
179
|
-
getBestTreeForDeposit,
|
|
180
|
-
} from "@veilo/sdk-core";
|
|
181
|
-
|
|
182
|
-
// Fetch decoded PrivacyConfig account
|
|
183
|
-
const config = await fetchPoolConfig(program, NATIVE_SOL_MINT);
|
|
184
|
-
|
|
185
|
-
// Check if a nullifier has been spent
|
|
186
|
-
const spent = await checkNullifierSpent(program, NATIVE_SOL_MINT, nullifier);
|
|
187
|
-
|
|
188
|
-
// Info for a single tree
|
|
189
|
-
const info = await getTreeInfo(program, NATIVE_SOL_MINT, 0);
|
|
190
|
-
// info = { treeId, leafCount, root, isFull }
|
|
191
|
-
|
|
192
|
-
// Info for all trees in a pool
|
|
193
|
-
const allInfo = await getAllTreeInfo(program, NATIVE_SOL_MINT);
|
|
194
|
-
|
|
195
|
-
// Pick the best tree for depositing (least full with capacity)
|
|
196
|
-
const best = await getBestTreeForDeposit(program, NATIVE_SOL_MINT);
|
|
197
|
-
// best = { treeId, leafCount, root }
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
### 4.4 UTXO Management
|
|
203
|
-
|
|
204
|
-
```ts
|
|
205
|
-
import {
|
|
206
|
-
generateKeypair,
|
|
207
|
-
keypairFromPrivateKey,
|
|
208
|
-
createUTXO,
|
|
209
|
-
createOwnedUTXO,
|
|
210
|
-
createOwnedZeroUTXO,
|
|
211
|
-
deriveNullifier,
|
|
212
|
-
type Keypair,
|
|
213
|
-
type UTXO,
|
|
214
|
-
type SerializedUTXO,
|
|
215
|
-
type InputUTXO,
|
|
216
|
-
} from "@veilo/sdk-core";
|
|
217
|
-
import { NATIVE_SOL_MINT } from "@veilo/sdk-core/config";
|
|
218
|
-
import { pubkeyToField } from "@veilo/sdk-core";
|
|
219
|
-
|
|
220
|
-
// Generate a random UTXO keypair
|
|
221
|
-
const keypair: Keypair = generateKeypair();
|
|
222
|
-
// keypair = { privateKey: bigint, publicKey: bigint }
|
|
223
|
-
|
|
224
|
-
// Restore from private key
|
|
225
|
-
const restored = keypairFromPrivateKey(privateKeyBigInt);
|
|
226
|
-
|
|
227
|
-
// Create an owned UTXO (includes private key)
|
|
228
|
-
const ownedUtxo: SerializedUTXO = createOwnedUTXO({
|
|
229
|
-
amount: 1_000_000_000n,
|
|
230
|
-
privateKey: keypair.privateKey,
|
|
231
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// Create a zero-value UTXO (for unused inputs/outputs)
|
|
235
|
-
const zeroUtxo = createOwnedZeroUTXO(pubkeyToField(NATIVE_SOL_MINT), keypair);
|
|
236
|
-
|
|
237
|
-
// Derive nullifier for spending
|
|
238
|
-
const pathIndex = 0; // leaf index in Merkle tree
|
|
239
|
-
const treeId = 0;
|
|
240
|
-
const nullifier = deriveNullifier(
|
|
241
|
-
ownedUtxo.privateKey,
|
|
242
|
-
ownedUtxo.commitment,
|
|
243
|
-
pathIndex,
|
|
244
|
-
treeId,
|
|
245
|
-
);
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
**UTXO commitment:** `Poseidon(amount, pubkey, blinding, mintAddress)`
|
|
249
|
-
|
|
250
|
-
**Nullifier:** `Poseidon(privateKey, commitment, pathIndex, treeId)`
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
### 4.5 UTXO Encryption
|
|
255
|
-
|
|
256
|
-
The SDK provides NaCl-based encryption for UTXO notes (relayer storage) and blind mailbox delivery (wallet-to-wallet).
|
|
257
|
-
|
|
258
|
-
```ts
|
|
259
|
-
import {
|
|
260
|
-
deriveEncryptionKeypair,
|
|
261
|
-
encryptUTXONote,
|
|
262
|
-
decryptUTXONote,
|
|
263
|
-
encryptBlindMailboxNote,
|
|
264
|
-
decryptBlindMailboxNote,
|
|
265
|
-
fetchAndDecryptNotes,
|
|
266
|
-
computeSignature,
|
|
267
|
-
inputUTXOToCircuitFormat,
|
|
268
|
-
type EncryptedNote,
|
|
269
|
-
type BlindMailboxNote,
|
|
270
|
-
type BlindMailboxNoteData,
|
|
271
|
-
type DecryptedNote,
|
|
272
|
-
} from "@veilo/sdk-core";
|
|
273
|
-
import { Keypair as SolanaKeypair } from "@solana/web3.js";
|
|
274
|
-
|
|
275
|
-
// Derive a NaCl encryption keypair from a UTXO private key
|
|
276
|
-
const encKeypair = deriveEncryptionKeypair(utxoKeypair.privateKey);
|
|
277
|
-
// encKeypair = { publicKey: Uint8Array[32], secretKey: Uint8Array[32] }
|
|
278
|
-
|
|
279
|
-
// Encrypt a UTXO note for relay storage
|
|
280
|
-
const encryptedNote: EncryptedNote = encryptUTXONote(
|
|
281
|
-
serializedUtxo, // SerializedUTXO
|
|
282
|
-
encKeypair.publicKey, // NaCl public key (Uint8Array[32])
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
// Decrypt a UTXO note
|
|
286
|
-
const decrypted: SerializedUTXO | null = decryptUTXONote(
|
|
287
|
-
encryptedNote,
|
|
288
|
-
encKeypair.secretKey, // NaCl secret key (Uint8Array[32])
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
// Blind mailbox: encrypt for a Solana wallet keypair
|
|
292
|
-
const recipientKeypair = SolanaKeypair.generate();
|
|
293
|
-
|
|
294
|
-
const mailboxNote: BlindMailboxNote = encryptBlindMailboxNote(
|
|
295
|
-
serializedUtxo,
|
|
296
|
-
recipientKeypair.publicKey.toBytes(), // ed25519 public key → X25519 DH
|
|
297
|
-
);
|
|
298
|
-
|
|
299
|
-
// Recipient decrypts using their Solana secret key (64-byte)
|
|
300
|
-
const mailboxDecrypted: DecryptedNote | null = decryptBlindMailboxNote(
|
|
301
|
-
mailboxNote,
|
|
302
|
-
recipientKeypair.secretKey, // 64-byte Solana secret key
|
|
303
|
-
);
|
|
304
|
-
|
|
305
|
-
// Compute UTXO signature (used in circuit)
|
|
306
|
-
const sig = computeSignature(utxoKeypair.privateKey, utxo.commitment);
|
|
307
|
-
|
|
308
|
-
// Format an InputUTXO for snarkjs circuit
|
|
309
|
-
const circuitFormat = inputUTXOToCircuitFormat(inputUtxo);
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
---
|
|
313
|
-
|
|
314
|
-
### 4.6 Merkle Tree Operations
|
|
315
|
-
|
|
316
|
-
```ts
|
|
317
|
-
import { MerkleTree } from "@veilo/sdk-core";
|
|
318
|
-
|
|
319
|
-
// Create a new Merkle tree (default depth: 22)
|
|
320
|
-
const tree = new MerkleTree();
|
|
321
|
-
|
|
322
|
-
// Insert commitments
|
|
323
|
-
const index = tree.insert(ownedUtxo.commitment);
|
|
324
|
-
|
|
325
|
-
// Current root
|
|
326
|
-
const root = tree.root();
|
|
327
|
-
|
|
328
|
-
// Merkle path for proof generation
|
|
329
|
-
const path = tree.path(index);
|
|
330
|
-
// path = { pathElements: Uint8Array[], pathIndices: number[] }
|
|
331
|
-
|
|
332
|
-
// Total leaves inserted
|
|
333
|
-
const count = tree.totalLeaves;
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
---
|
|
337
|
-
|
|
338
|
-
### 4.7 Transaction Operations
|
|
339
|
-
|
|
340
|
-
All transaction functions return `Promise<string>` (the transaction signature).
|
|
341
|
-
|
|
342
|
-
#### Deposits
|
|
343
|
-
|
|
344
|
-
```ts
|
|
345
|
-
import { deposit, type DepositResult } from "@veilo/sdk-core";
|
|
346
|
-
|
|
347
|
-
const result: DepositResult = await deposit({
|
|
348
|
-
program,
|
|
349
|
-
depositor: depositorKeypair,
|
|
350
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
351
|
-
amount: 1_000_000_000n, // 1 SOL
|
|
352
|
-
recipientPubkey: pubkeyToField(depositorKeypair.publicKey), // bigint
|
|
353
|
-
tree,
|
|
354
|
-
proofBuilder,
|
|
355
|
-
treeId: 0,
|
|
356
|
-
});
|
|
357
|
-
// result = { outputUTXOs, leafIndices, root }
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
#### Withdrawals
|
|
361
|
-
|
|
362
|
-
```ts
|
|
363
|
-
import { withdraw, type WithdrawResult } from "@veilo/sdk-core";
|
|
364
|
-
|
|
365
|
-
const result: WithdrawResult = await withdraw({
|
|
366
|
-
program,
|
|
367
|
-
relayer: relayerKeypair,
|
|
368
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
369
|
-
amount: 900_000_000n, // 0.9 SOL
|
|
370
|
-
fee: 100_000_000n, // 0.1 SOL to relayer
|
|
371
|
-
inputs: [inputUtxo1, zeroInputUtxo],
|
|
372
|
-
outputs: [changeUtxo, zeroOutputUtxo],
|
|
373
|
-
recipient: recipientKeypair.publicKey,
|
|
374
|
-
tree,
|
|
375
|
-
proofBuilder,
|
|
376
|
-
treeId: 0,
|
|
377
|
-
});
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
#### Private Transfers
|
|
381
|
-
|
|
382
|
-
```ts
|
|
383
|
-
import { privateTransfer, type TransferResult } from "@veilo/sdk-core";
|
|
384
|
-
|
|
385
|
-
const result: TransferResult = await privateTransfer({
|
|
386
|
-
program,
|
|
387
|
-
relayer: relayerKeypair,
|
|
388
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
389
|
-
inputs: [inputUtxo1, zeroInputUtxo],
|
|
390
|
-
outputs: [recipientUtxo, changeUtxo],
|
|
391
|
-
recipient: relayerKeypair.publicKey,
|
|
392
|
-
tree,
|
|
393
|
-
proofBuilder,
|
|
394
|
-
treeId: 0,
|
|
395
|
-
});
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
#### Low-Level `transact`
|
|
399
|
-
|
|
400
|
-
```ts
|
|
401
|
-
import { transact } from "@veilo/sdk-core";
|
|
402
|
-
|
|
403
|
-
const signature: string = await transact({
|
|
404
|
-
program,
|
|
405
|
-
relayer: relayerKeypair,
|
|
406
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
407
|
-
inputTreeId: 0,
|
|
408
|
-
outputTreeId: 0,
|
|
409
|
-
root: tree.root(),
|
|
410
|
-
publicAmount: 0n,
|
|
411
|
-
inputNullifiers: [nullifier1, nullifier2],
|
|
412
|
-
outputCommitments: [output1.commitment, output2.commitment],
|
|
413
|
-
extData: { recipient, relayer: relayerPubkey, fee: 0n, refund: 0n, claimant },
|
|
414
|
-
proof,
|
|
415
|
-
});
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
---
|
|
419
|
-
|
|
420
|
-
#### Wallet-agnostic shielding
|
|
421
|
-
|
|
422
|
-
`shield()` builds an unsigned v0 deposit transaction for any Solana wallet to
|
|
423
|
-
sign. The signer funds the deposit, while the resulting private note can belong
|
|
424
|
-
to a different Veilo user. The SDK never receives a wallet secret key and never
|
|
425
|
-
broadcasts on the caller's behalf.
|
|
50
|
+
`shield()` creates an unsigned transaction. Your application asks the user's
|
|
51
|
+
wallet to sign it, submits it, and then finalizes the new private note.
|
|
426
52
|
|
|
427
53
|
```ts
|
|
54
|
+
import { Connection } from "@solana/web3.js";
|
|
428
55
|
import {
|
|
429
56
|
createTransactionProver,
|
|
57
|
+
finalizeShield,
|
|
430
58
|
resolveShieldOwner,
|
|
431
59
|
shield,
|
|
432
60
|
} from "@veilo/sdk-core";
|
|
433
61
|
|
|
62
|
+
const connection = new Connection(process.env.SOLANA_RPC_URL!, "confirmed");
|
|
63
|
+
|
|
64
|
+
// `wallet` is any connected Solana wallet with `publicKey` and
|
|
65
|
+
// `signTransaction` methods.
|
|
434
66
|
const owner = await resolveShieldOwner({ username: "alice" });
|
|
67
|
+
const prover = createTransactionProver({
|
|
68
|
+
wasmPath: "/circuits/transaction.wasm",
|
|
69
|
+
zkeyPath: "/circuits/transaction_final.zkey",
|
|
70
|
+
});
|
|
71
|
+
|
|
435
72
|
const result = await shield({
|
|
436
73
|
connection,
|
|
437
|
-
amount:
|
|
438
|
-
mint: USDC_MINT,
|
|
74
|
+
amount: 1_000_000_000n, // 1 SOL in lamports
|
|
439
75
|
owner,
|
|
440
76
|
signer: { publicKey: wallet.publicKey },
|
|
441
|
-
prover
|
|
77
|
+
prover,
|
|
442
78
|
});
|
|
443
79
|
|
|
444
80
|
const signed = await wallet.signTransaction(result.transaction);
|
|
445
81
|
const signature = await connection.sendRawTransaction(signed.serialize());
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
Use `rebuild()` if the blockhash or deadline expires, and call
|
|
449
|
-
`finalizeShield()` after confirmation to obtain the authoritative Merkle leaf
|
|
450
|
-
index. See [SHIELD_INTEGRATION.md](./SHIELD_INTEGRATION.md) for the complete
|
|
451
|
-
build → sign → submit → finalize flow, retry rules, owner-key invariant, and
|
|
452
|
-
fee/rent requirements.
|
|
453
|
-
|
|
454
|
-
---
|
|
455
82
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
83
|
+
const confirmation = await connection.confirmTransaction(
|
|
84
|
+
{
|
|
85
|
+
signature,
|
|
86
|
+
blockhash: result.blockhash,
|
|
87
|
+
lastValidBlockHeight: result.lastValidBlockHeight,
|
|
88
|
+
},
|
|
89
|
+
"confirmed",
|
|
90
|
+
);
|
|
459
91
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
getSwapExecutorPda,
|
|
464
|
-
fundNativeSource,
|
|
465
|
-
type SwapParams,
|
|
466
|
-
type SwapProofStruct,
|
|
467
|
-
} from "@veilo/sdk-core";
|
|
92
|
+
if (confirmation.value.err) {
|
|
93
|
+
throw new Error("Shield transaction failed");
|
|
94
|
+
}
|
|
468
95
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
destMint,
|
|
475
|
-
sourceRoot: tree.root(),
|
|
476
|
-
sourceTreeId: 0,
|
|
477
|
-
destTreeId: 0,
|
|
478
|
-
inputNullifiers: [nullifier0, nullifier1],
|
|
479
|
-
outputCommitments: [changeCommitment, destCommitment],
|
|
480
|
-
proof, // SwapProofStruct
|
|
481
|
-
swapParams: {
|
|
482
|
-
minAmountOut: 950_000_000n,
|
|
483
|
-
deadline: BigInt(Math.floor(Date.now() / 1000) + 60),
|
|
484
|
-
sourceMint,
|
|
485
|
-
destMint,
|
|
486
|
-
destAmount: 950_000_000n,
|
|
487
|
-
swapDataHash: new Uint8Array(32), // SHA-256 of DEX ix bytes, or zeros
|
|
488
|
-
},
|
|
489
|
-
swapAmount: 1_000_000_000n,
|
|
490
|
-
swapData: jupiterInstructionBytes, // Buffer
|
|
491
|
-
extData: { recipient, relayer: relayerPubkey, fee, refund: 0n, claimant },
|
|
492
|
-
sourceVaultTokenAccount,
|
|
493
|
-
sourceMintAccount,
|
|
494
|
-
destVaultTokenAccount,
|
|
495
|
-
destMintAccount,
|
|
496
|
-
relayerTokenAccount,
|
|
497
|
-
swapProgram: JUPITER_PROGRAM_ID,
|
|
498
|
-
jupiterEventAuthority,
|
|
96
|
+
const finalized = await finalizeShield({
|
|
97
|
+
connection,
|
|
98
|
+
signature,
|
|
99
|
+
note: result.note,
|
|
100
|
+
owner,
|
|
499
101
|
});
|
|
500
102
|
|
|
501
|
-
|
|
502
|
-
const fundIx = await fundNativeSource({
|
|
503
|
-
program,
|
|
504
|
-
relayer: relayerKeypair,
|
|
505
|
-
sourceMint: NATIVE_SOL_MINT,
|
|
506
|
-
destMint,
|
|
507
|
-
inputNullifier0: nullifier0,
|
|
508
|
-
swapAmount: 1_000_000_000n,
|
|
509
|
-
});
|
|
510
|
-
// Returns TransactionInstruction — must be first ix in same tx as transact_swap
|
|
103
|
+
console.log("Private note created at leaf", finalized.leafIndex);
|
|
511
104
|
```
|
|
512
105
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
---
|
|
516
|
-
|
|
517
|
-
### 4.9 Event Scanning & Tree Reconstruction
|
|
106
|
+
To shield an SPL token, pass its mint:
|
|
518
107
|
|
|
519
108
|
```ts
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
// Scan all commitment events for a mint (paginated by signature)
|
|
529
|
-
const { events, latestSignature } = await scanCommitmentEvents({
|
|
530
|
-
program,
|
|
531
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
532
|
-
treeId: 0,
|
|
533
|
-
beforeSignature: undefined, // or last known signature for pagination
|
|
534
|
-
limit: 1000,
|
|
535
|
-
});
|
|
536
|
-
// events: CommitmentEvent[]
|
|
537
|
-
// CommitmentEvent = { commitment, leafIndex, newRoot, timestamp, mintAddress, treeId }
|
|
538
|
-
|
|
539
|
-
// Scan spent nullifier events
|
|
540
|
-
const { events: nullEvents } = await scanNullifierEvents({
|
|
541
|
-
program,
|
|
542
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
543
|
-
beforeSignature: undefined,
|
|
544
|
-
limit: 1000,
|
|
545
|
-
});
|
|
546
|
-
// NullifierSpentEvent = { nullifier, mintAddress, treeId }
|
|
547
|
-
|
|
548
|
-
// Reconstruct a Merkle tree from on-chain events
|
|
549
|
-
const {
|
|
550
|
-
tree,
|
|
551
|
-
events: allEvents,
|
|
552
|
-
latestSignature: sig,
|
|
553
|
-
} = await buildTreeFromEvents({
|
|
554
|
-
program,
|
|
555
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
556
|
-
treeId: 0,
|
|
109
|
+
const result = await shield({
|
|
110
|
+
connection,
|
|
111
|
+
mint: usdcMint,
|
|
112
|
+
amount: 5_000_000n, // 5 USDC when the mint has 6 decimals
|
|
113
|
+
owner,
|
|
114
|
+
signer: { publicKey: wallet.publicKey },
|
|
115
|
+
prover,
|
|
557
116
|
});
|
|
558
117
|
```
|
|
559
118
|
|
|
560
|
-
|
|
119
|
+
Keep `result.note` private. It contains the information needed to recover the
|
|
120
|
+
shielded funds. `finalizeShield()` gives you the authoritative leaf index after
|
|
121
|
+
the transaction lands.
|
|
561
122
|
|
|
562
|
-
|
|
123
|
+
If the blockhash expires before submission, reuse the proof with `rebuild()`:
|
|
563
124
|
|
|
564
125
|
```ts
|
|
565
|
-
import {
|
|
566
|
-
prepareTransactionInputs,
|
|
567
|
-
formatInputsForSnarkjs,
|
|
568
|
-
computeExtDataHash,
|
|
569
|
-
encodeSnarkjsProofToTransactionProof,
|
|
570
|
-
packProofToBytes,
|
|
571
|
-
computeSwapParamsHash,
|
|
572
|
-
computeSwapDataHash,
|
|
573
|
-
type ExtData,
|
|
574
|
-
type TransactionCircuitInputs,
|
|
575
|
-
} from "@veilo/sdk-core";
|
|
576
|
-
|
|
577
|
-
// Prepare inputs for the transaction circuit
|
|
578
|
-
const circuitInputs: TransactionCircuitInputs = prepareTransactionInputs({
|
|
579
|
-
root: tree.root(),
|
|
580
|
-
publicAmount: 1_000_000_000n,
|
|
581
|
-
extData: { recipient, relayer: relayerPubkey, fee: 0n, refund: 0n, claimant },
|
|
582
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
583
|
-
inputs: [input1, input2],
|
|
584
|
-
outputs: [output1, output2],
|
|
585
|
-
inputTreeId: 0,
|
|
586
|
-
outputTreeId: 0,
|
|
587
|
-
});
|
|
126
|
+
import { rebuild } from "@veilo/sdk-core";
|
|
588
127
|
|
|
589
|
-
|
|
590
|
-
const snarkjsInputs = formatInputsForSnarkjs(circuitInputs);
|
|
591
|
-
|
|
592
|
-
// After proof generation:
|
|
593
|
-
// const { proof } = await snarkjs.groth16.fullProve(snarkjsInputs, wasmPath, zkeyPath);
|
|
594
|
-
// const transactionProof = encodeSnarkjsProofToTransactionProof(proof);
|
|
595
|
-
|
|
596
|
-
// Compute ext data hash (matches on-chain computation)
|
|
597
|
-
const extDataHash = computeExtDataHash({
|
|
598
|
-
recipient,
|
|
599
|
-
relayer,
|
|
600
|
-
fee: 0n,
|
|
601
|
-
refund: 0n,
|
|
602
|
-
claimant,
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
// Compute swap param/data hashes (for swap circuit inputs)
|
|
606
|
-
const swapParamsHash = computeSwapParamsHash(swapParams);
|
|
607
|
-
const swapDataHash = computeSwapDataHash(jupiterInstructionBytes);
|
|
128
|
+
const refreshed = await rebuild(result, { connection });
|
|
608
129
|
```
|
|
609
130
|
|
|
610
|
-
|
|
131
|
+
A stale Merkle root needs a new call to `shield()` because it requires a new
|
|
132
|
+
proof.
|
|
611
133
|
|
|
612
|
-
|
|
134
|
+
## Cloak Partner API
|
|
613
135
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
DEFAULT_FEE_BPS,
|
|
619
|
-
} from "@veilo/sdk-core/config";
|
|
136
|
+
Cloak is the simplest route for partner applications that want a private send
|
|
137
|
+
or cross-asset private swap. The SDK handles request types, API authentication,
|
|
138
|
+
transaction decoding, polling, and structured errors. It never signs for the
|
|
139
|
+
user.
|
|
620
140
|
|
|
621
|
-
|
|
622
|
-
|
|
141
|
+
Keep your Cloak API key on a trusted server. Do not include it in a browser or
|
|
142
|
+
mobile bundle.
|
|
623
143
|
|
|
624
|
-
|
|
625
|
-
const swapFee = computeSwapFee(swapAmount, feeBps);
|
|
626
|
-
```
|
|
627
|
-
|
|
628
|
-
---
|
|
629
|
-
|
|
630
|
-
### 4.12 Relayer & Admin Management
|
|
144
|
+
### Create an order on your server
|
|
631
145
|
|
|
632
146
|
```ts
|
|
633
|
-
import {
|
|
147
|
+
import { VeiloCloakClient } from "@veilo/sdk-core/cloak";
|
|
634
148
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
program,
|
|
638
|
-
admin: adminKeypair,
|
|
639
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
640
|
-
newRelayer: relayerPubkey,
|
|
149
|
+
const cloak = new VeiloCloakClient({
|
|
150
|
+
apiKey: process.env.VEILO_CLOAK_KEY!,
|
|
641
151
|
});
|
|
642
152
|
|
|
643
|
-
//
|
|
644
|
-
await
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
153
|
+
// The production API defaults to https://api.veilo.network/.
|
|
154
|
+
const { quote } = await cloak.getQuote({
|
|
155
|
+
amount: "100000000", // raw token units
|
|
156
|
+
sourceAssetId: "veilo-usdc",
|
|
157
|
+
destinationAssetId: "veilo-usdc",
|
|
158
|
+
senderAddress,
|
|
159
|
+
recipientAddress,
|
|
160
|
+
mode: "exact_in",
|
|
649
161
|
});
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
---
|
|
653
|
-
|
|
654
|
-
### 4.13 Poseidon Utilities
|
|
655
|
-
|
|
656
|
-
```ts
|
|
657
|
-
import {
|
|
658
|
-
initPoseidon,
|
|
659
|
-
poseidon1,
|
|
660
|
-
poseidon2,
|
|
661
|
-
poseidon3,
|
|
662
|
-
poseidon4,
|
|
663
|
-
pubkeyToField,
|
|
664
|
-
bytesToBigIntBE,
|
|
665
|
-
bigIntToBytesBE,
|
|
666
|
-
BN254_FR_MODULUS,
|
|
667
|
-
} from "@veilo/sdk-core";
|
|
668
162
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
// Convert a Solana PublicKey to a BN254 field element
|
|
678
|
-
const field = pubkeyToField(NATIVE_SOL_MINT);
|
|
679
|
-
|
|
680
|
-
// Byte ↔ bigint helpers (big-endian)
|
|
681
|
-
const n = bytesToBigIntBE(bytes32);
|
|
682
|
-
const b = bigIntToBytesBE(someField, 32);
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
---
|
|
686
|
-
|
|
687
|
-
### 4.14 Error Utilities
|
|
688
|
-
|
|
689
|
-
```ts
|
|
690
|
-
import { parseOnChainError } from "@veilo/sdk-core";
|
|
691
|
-
|
|
692
|
-
try {
|
|
693
|
-
await transactSwap({ ... });
|
|
694
|
-
} catch (err) {
|
|
695
|
-
// Returns a human-readable error string from Anchor/program errors
|
|
696
|
-
const msg = parseOnChainError(err);
|
|
697
|
-
console.error("Swap failed:", msg);
|
|
698
|
-
}
|
|
163
|
+
const { order } = await cloak.createOrder(
|
|
164
|
+
{
|
|
165
|
+
quote, // return the complete quote without changing it
|
|
166
|
+
senderAddress,
|
|
167
|
+
recipientAddress,
|
|
168
|
+
},
|
|
169
|
+
{ idempotencyKey: crypto.randomUUID() },
|
|
170
|
+
);
|
|
699
171
|
```
|
|
700
172
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
173
|
+
For a cross-asset swap, use a different `destinationAssetId` and optionally add
|
|
174
|
+
`slippageBps` to the quote request. Use `listTokens()` to discover supported
|
|
175
|
+
asset IDs and their current limits.
|
|
704
176
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
Veilo uses a UTXO privacy model inspired by Zcash and Tornado Cash Nova:
|
|
708
|
-
|
|
709
|
-
- **Inputs**: 2 UTXOs (zero-value for deposits)
|
|
710
|
-
- **Outputs**: 2 UTXOs (zero-value for withdrawals)
|
|
711
|
-
- **Public Amount**: net pool change — positive = deposit, negative = withdrawal, zero = private transfer or swap
|
|
712
|
-
|
|
713
|
-
Each transaction consumes 2 input UTXOs (Merkle proofs), creates 2 output UTXOs (commitments inserted to tree), and generates 2 nullifiers to prevent double-spend.
|
|
714
|
-
|
|
715
|
-
### Swap Architecture
|
|
716
|
-
|
|
717
|
-
Private swaps require two instructions in a **single atomic transaction**:
|
|
718
|
-
|
|
719
|
-
1. `fund_native_source` — pre-funds the swap executor with SOL from the vault (native SOL pools only)
|
|
720
|
-
2. `transact_swap` — verifies the ZK proof, spends input UTXOs, creates output UTXOs, and executes the DEX swap
|
|
721
|
-
|
|
722
|
-
`transactSwap()` handles this automatically. The on-chain program validates atomicity via the instructions sysvar.
|
|
723
|
-
|
|
724
|
-
### Privacy Guarantees
|
|
725
|
-
|
|
726
|
-
- **Commitment hiding**: amount, owner, blinding are hidden via Poseidon
|
|
727
|
-
- **Nullifier uniqueness**: each UTXO can only be spent once
|
|
728
|
-
- **Unlinkability**: no public link between inputs and outputs
|
|
729
|
-
- **ZK proofs**: Groth16 verified on-chain
|
|
730
|
-
|
|
731
|
-
### Constants
|
|
177
|
+
You can override the API address for another environment. Both the origin and
|
|
178
|
+
the full Cloak path are accepted:
|
|
732
179
|
|
|
733
180
|
```ts
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
DEFAULT_FEE_BPS, // 50 (0.5%)
|
|
739
|
-
sol, // sol(1) === 1_000_000_000n
|
|
740
|
-
} from "@veilo/sdk-core/config";
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
### Type Exports
|
|
744
|
-
|
|
745
|
-
```ts
|
|
746
|
-
import type {
|
|
747
|
-
// UTXO
|
|
748
|
-
Keypair,
|
|
749
|
-
UTXO,
|
|
750
|
-
SerializedUTXO,
|
|
751
|
-
InputUTXO,
|
|
752
|
-
// Encryption
|
|
753
|
-
EncryptedNote,
|
|
754
|
-
BlindMailboxNote,
|
|
755
|
-
BlindMailboxNoteData,
|
|
756
|
-
DecryptedNote,
|
|
757
|
-
// Proof
|
|
758
|
-
ExtData,
|
|
759
|
-
TransactionCircuitInputs,
|
|
760
|
-
TransactionProofStruct,
|
|
761
|
-
RawProof,
|
|
762
|
-
TransactionProofBuilder,
|
|
763
|
-
// Swap
|
|
764
|
-
SwapProofStruct,
|
|
765
|
-
SwapParams,
|
|
766
|
-
// Tree / events
|
|
767
|
-
MerklePath,
|
|
768
|
-
CircuitMerklePath,
|
|
769
|
-
TreeInfo,
|
|
770
|
-
CommitmentEvent,
|
|
771
|
-
NullifierSpentEvent,
|
|
772
|
-
// Results
|
|
773
|
-
DepositResult,
|
|
774
|
-
WithdrawResult,
|
|
775
|
-
TransferResult,
|
|
776
|
-
// Config
|
|
777
|
-
PoolInitConfig,
|
|
778
|
-
PrivacyConfigAccount,
|
|
779
|
-
GlobalConfigAccount,
|
|
780
|
-
} from "@veilo/sdk-core";
|
|
781
|
-
```
|
|
782
|
-
|
|
783
|
-
---
|
|
784
|
-
|
|
785
|
-
## 6. Development
|
|
786
|
-
|
|
787
|
-
```bash
|
|
788
|
-
# Run tests (requires devnet or local validator)
|
|
789
|
-
npm test
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
---
|
|
793
|
-
|
|
794
|
-
## 7. Resources
|
|
795
|
-
|
|
796
|
-
- **Repository**: https://github.com/VeiloSolana/veilo-sdk
|
|
797
|
-
- **Circomlibjs**: https://github.com/iden3/circomlibjs
|
|
798
|
-
- **Poseidon Hash**: https://www.poseidon-hash.info/
|
|
799
|
-
|
|
800
|
-
---
|
|
801
|
-
|
|
802
|
-
## License
|
|
803
|
-
|
|
804
|
-
ISC
|
|
805
|
-
|
|
806
|
-
This package provides a complete UTXO-based privacy protocol implementation on Solana with:
|
|
807
|
-
|
|
808
|
-
- **UTXO Model**: Full support for unspent transaction outputs with Poseidon commitments
|
|
809
|
-
- **Multi-Tree Support**: Multiple concurrent Merkle trees for improved scalability
|
|
810
|
-
- **ZK Proofs**: Integration with Circom circuits for private transactions
|
|
811
|
-
- **Flexible Operations**: Deposits, withdrawals, and private transfers
|
|
812
|
-
- **Poseidon Hashing**: BN254-curve compatible hashing using circomlibjs
|
|
813
|
-
- **Merkle Trees**: Off-chain Merkle tree management with proof generation
|
|
814
|
-
- **Relayer Support**: Built-in relayer infrastructure for private withdrawals
|
|
815
|
-
|
|
816
|
-
> **Status:** Active development. The SDK supports full transaction privacy with ZK-SNARK proofs.
|
|
817
|
-
> Proofs are generated off-chain and verified on-chain using Groth16.
|
|
818
|
-
|
|
819
|
-
---
|
|
820
|
-
|
|
821
|
-
## 1. Installation
|
|
822
|
-
|
|
823
|
-
```bash
|
|
824
|
-
npm install @veilo/sdk-core
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
Or from source:
|
|
828
|
-
|
|
829
|
-
```bash
|
|
830
|
-
cd core-sdk
|
|
831
|
-
npm install
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
---
|
|
835
|
-
|
|
836
|
-
## 2. Prerequisites
|
|
837
|
-
|
|
838
|
-
You need:
|
|
839
|
-
|
|
840
|
-
- A running Solana validator (localnet/devnet/mainnet):
|
|
841
|
-
|
|
842
|
-
```bash
|
|
843
|
-
solana-test-validator
|
|
844
|
-
```
|
|
845
|
-
|
|
846
|
-
- The `privacy-pool` program deployed to the network
|
|
847
|
-
- The `privacy-pool` Anchor IDL available:
|
|
848
|
-
|
|
849
|
-
```text
|
|
850
|
-
idl/idl/privacy_pool.json
|
|
851
|
-
```
|
|
852
|
-
|
|
853
|
-
- A funded keypair:
|
|
854
|
-
|
|
855
|
-
```bash
|
|
856
|
-
solana config set --url http://127.0.0.1:8899
|
|
857
|
-
solana-keygen new --outfile ~/.config/solana/id.json
|
|
858
|
-
solana airdrop 10
|
|
859
|
-
```
|
|
860
|
-
|
|
861
|
-
Environment variables:
|
|
862
|
-
|
|
863
|
-
```bash
|
|
864
|
-
export ANCHOR_PROVIDER_URL=http://127.0.0.1:8899
|
|
865
|
-
export ANCHOR_WALLET=$HOME/.config/solana/id.json
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
---
|
|
869
|
-
|
|
870
|
-
## 3. Build
|
|
871
|
-
|
|
872
|
-
```bash
|
|
873
|
-
npm run build
|
|
181
|
+
new VeiloCloakClient({
|
|
182
|
+
baseUrl: "https://api.veilo.network/", // `/cloak/v1` also works here
|
|
183
|
+
apiKey: process.env.VEILO_CLOAK_KEY!,
|
|
184
|
+
});
|
|
874
185
|
```
|
|
875
186
|
|
|
876
|
-
|
|
187
|
+
### Sign in the user's application
|
|
877
188
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
### 4.1 PDA Helpers
|
|
189
|
+
Send the returned `order` to the user's application, then deserialize and sign
|
|
190
|
+
its transaction:
|
|
881
191
|
|
|
882
192
|
```ts
|
|
883
|
-
import {
|
|
884
|
-
getPoolPdas,
|
|
885
|
-
getNoteTreePda,
|
|
886
|
-
getGlobalConfigPda,
|
|
887
|
-
getNullifierMarkerPda,
|
|
888
|
-
} from "@veilo/sdk-core";
|
|
889
|
-
import { PublicKey } from "@solana/web3.js";
|
|
890
|
-
|
|
891
|
-
const programId = new PublicKey(
|
|
892
|
-
"YourProgram1111111111111111111111111111111111",
|
|
893
|
-
);
|
|
894
|
-
const mintAddress = new PublicKey(
|
|
895
|
-
"So11111111111111111111111111111111111111112",
|
|
896
|
-
); // Native SOL
|
|
897
|
-
|
|
898
|
-
// Get pool PDAs
|
|
899
|
-
const { config, vault, nullifiers } = getPoolPdas(programId, mintAddress);
|
|
193
|
+
import { deserializeCloakTransaction } from "@veilo/sdk-core/cloak";
|
|
900
194
|
|
|
901
|
-
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
const globalConfig = getGlobalConfigPda(programId);
|
|
906
|
-
|
|
907
|
-
// Get nullifier marker PDA
|
|
908
|
-
const nullifier = new Uint8Array(32);
|
|
909
|
-
const marker = getNullifierMarkerPda(programId, mintAddress, 0, nullifier);
|
|
195
|
+
const transaction = deserializeCloakTransaction(order);
|
|
196
|
+
const signed = await wallet.signTransaction(transaction);
|
|
197
|
+
const signature = await connection.sendRawTransaction(signed.serialize());
|
|
198
|
+
await connection.confirmTransaction(signature, "confirmed");
|
|
910
199
|
```
|
|
911
200
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
- Config: `["privacy_config_v3", mint_address]`
|
|
915
|
-
- Vault: `["privacy_vault_v3", mint_address]`
|
|
916
|
-
- Note Tree: `["privacy_note_tree_v3", mint_address, tree_id]`
|
|
917
|
-
- Nullifiers: `["privacy_nullifiers_v3", mint_address]`
|
|
918
|
-
- Nullifier Marker: `["privacy_nullifier_v3", mint_address, tree_id, nullifier]`
|
|
919
|
-
- Global Config: `["global_config_v1"]`
|
|
920
|
-
|
|
921
|
-
---
|
|
922
|
-
|
|
923
|
-
### 4.2 Pool Initialization
|
|
201
|
+
Send the signature back to your server. The deposit notification is optional,
|
|
202
|
+
but it can reduce processing latency:
|
|
924
203
|
|
|
925
204
|
```ts
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
initializePool,
|
|
930
|
-
updatePoolConfig,
|
|
931
|
-
addMerkleTree,
|
|
932
|
-
getPoolConfig,
|
|
933
|
-
} from "@veilo/sdk-core";
|
|
934
|
-
import { NATIVE_SOL_MINT, sol } from "@veilo/sdk-core/config";
|
|
935
|
-
|
|
936
|
-
// Initialize global config (once per program)
|
|
937
|
-
await initializeGlobalConfig({
|
|
938
|
-
program,
|
|
939
|
-
admin: adminKeypair,
|
|
205
|
+
await cloak.notifyDeposit({
|
|
206
|
+
trackingId: order.trackingId,
|
|
207
|
+
txSignature: signature,
|
|
940
208
|
});
|
|
941
209
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
payer: adminKeypair,
|
|
946
|
-
admin: adminKeypair,
|
|
947
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
948
|
-
minDepositAmount: sol(0.1), // 0.1 SOL
|
|
949
|
-
maxDepositAmount: sol(100), // 100 SOL
|
|
950
|
-
minWithdrawAmount: sol(0.1),
|
|
951
|
-
maxWithdrawAmount: sol(100),
|
|
952
|
-
feeBps: 50, // 0.5%
|
|
953
|
-
feeErrorMarginBps: 10, // 0.1% margin
|
|
954
|
-
minWithdrawalFee: 1_000_000n, // 0.001 SOL minimum
|
|
210
|
+
const finalStatus = await cloak.waitForFinalStatus(order.trackingId, {
|
|
211
|
+
intervalMs: 3_000,
|
|
212
|
+
timeoutMs: 20 * 60_000,
|
|
955
213
|
});
|
|
956
214
|
|
|
957
|
-
|
|
958
|
-
await addMerkleTree({
|
|
959
|
-
program,
|
|
960
|
-
payer: adminKeypair,
|
|
961
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
962
|
-
treeId: 0,
|
|
963
|
-
});
|
|
964
|
-
|
|
965
|
-
// Update pool configuration
|
|
966
|
-
await updatePoolConfig({
|
|
967
|
-
program,
|
|
968
|
-
admin: adminKeypair,
|
|
969
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
970
|
-
feeBps: 30, // Change to 0.3%
|
|
971
|
-
});
|
|
972
|
-
|
|
973
|
-
// Read pool configuration
|
|
974
|
-
const poolConfig = await getPoolConfig(program, NATIVE_SOL_MINT);
|
|
975
|
-
console.log("TVL:", poolConfig.totalTvl);
|
|
976
|
-
console.log("Fee:", poolConfig.feeBps, "bps");
|
|
977
|
-
console.log("Num Trees:", poolConfig.numTrees);
|
|
215
|
+
console.log(finalStatus.status);
|
|
978
216
|
```
|
|
979
217
|
|
|
980
|
-
|
|
218
|
+
If an unfunded order's transaction expires, call
|
|
219
|
+
`refreshTransaction(order.trackingId)` and ask the user to sign the refreshed
|
|
220
|
+
transaction.
|
|
981
221
|
|
|
982
|
-
|
|
222
|
+
## Full private wallet flows
|
|
983
223
|
|
|
984
|
-
The SDK
|
|
224
|
+
The SDK supports all Veilo privacy-pool operations. Pick the highest-level API
|
|
225
|
+
that fits your application:
|
|
985
226
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
createOwnedZeroUTXO,
|
|
993
|
-
deriveNullifier,
|
|
994
|
-
type Keypair,
|
|
995
|
-
type UTXO,
|
|
996
|
-
type SerializedUTXO,
|
|
997
|
-
type InputUTXO,
|
|
998
|
-
} from "@veilo/sdk-core";
|
|
999
|
-
import { NATIVE_SOL_MINT } from "@veilo/sdk-core/config";
|
|
1000
|
-
import { pubkeyToField } from "@veilo/sdk-core";
|
|
227
|
+
| Operation | Managed relayer call | Direct SDK helper |
|
|
228
|
+
| --- | --- | --- |
|
|
229
|
+
| Deposit | Not required | `shield()` or `deposit()` |
|
|
230
|
+
| Withdraw | `submitWithdraw()` | `withdraw()` |
|
|
231
|
+
| Private transfer | `submitPrivateTransfer()` | `privateTransfer()` |
|
|
232
|
+
| Private swap | `submitPrivateSwap()` | `buildPrivateSwapInstructions()` or `transactSwap()` |
|
|
1001
233
|
|
|
1002
|
-
|
|
1003
|
-
const keypair: Keypair = generateKeypair();
|
|
1004
|
-
// keypair = { privateKey: bigint, publicKey: bigint }
|
|
234
|
+
### Use the relayer client
|
|
1005
235
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
// Create an owned UTXO (includes private key)
|
|
1010
|
-
const ownedUtxo: SerializedUTXO = createOwnedUTXO({
|
|
1011
|
-
amount: 1_000_000_000n,
|
|
1012
|
-
privateKey: keypair.privateKey,
|
|
1013
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
1014
|
-
});
|
|
1015
|
-
|
|
1016
|
-
// Create a zero UTXO (for unused inputs/outputs)
|
|
1017
|
-
const zeroUtxo = createOwnedZeroUTXO(pubkeyToField(NATIVE_SOL_MINT), keypair);
|
|
1018
|
-
|
|
1019
|
-
// Derive nullifier for spending
|
|
1020
|
-
const nullifier = deriveNullifier(
|
|
1021
|
-
ownedUtxo.privateKey,
|
|
1022
|
-
ownedUtxo.commitment,
|
|
1023
|
-
0, // pathIndex in Merkle tree
|
|
1024
|
-
0, // treeId
|
|
1025
|
-
);
|
|
1026
|
-
```
|
|
1027
|
-
|
|
1028
|
-
**UTXO commitment formula:**
|
|
1029
|
-
|
|
1030
|
-
```
|
|
1031
|
-
commitment = Poseidon(amount, pubkey, blinding, mintAddress)
|
|
1032
|
-
```
|
|
1033
|
-
|
|
1034
|
-
**Nullifier formula:**
|
|
1035
|
-
|
|
1036
|
-
```
|
|
1037
|
-
nullifier = Poseidon(privateKey, commitment, pathIndex, treeId)
|
|
1038
|
-
```
|
|
1039
|
-
|
|
1040
|
-
---
|
|
1041
|
-
|
|
1042
|
-
### 4.4 Merkle Tree Operations
|
|
1043
|
-
|
|
1044
|
-
```ts
|
|
1045
|
-
import { MerkleTree } from "@veilo/sdk-core";
|
|
1046
|
-
|
|
1047
|
-
// Create a new Merkle tree (default depth: 20)
|
|
1048
|
-
const tree = new MerkleTree();
|
|
1049
|
-
|
|
1050
|
-
// Insert commitments
|
|
1051
|
-
const index1 = tree.insert(ownedUtxo1.commitment);
|
|
1052
|
-
const index2 = tree.insert(ownedUtxo2.commitment);
|
|
1053
|
-
|
|
1054
|
-
// Get current root
|
|
1055
|
-
const root = tree.root();
|
|
1056
|
-
|
|
1057
|
-
// Get Merkle path for proof generation
|
|
1058
|
-
const path = tree.path(index1);
|
|
1059
|
-
// path = { pathElements: Uint8Array[], pathIndices: number[] }
|
|
1060
|
-
|
|
1061
|
-
// Get number of leaves
|
|
1062
|
-
const numLeaves = tree.totalLeaves;
|
|
1063
|
-
|
|
1064
|
-
// Custom tree depth
|
|
1065
|
-
const deepTree = new MerkleTree(25); // 25 levels
|
|
1066
|
-
```
|
|
1067
|
-
|
|
1068
|
-
The Merkle tree uses Poseidon hash for all internal nodes.
|
|
1069
|
-
|
|
1070
|
-
---
|
|
1071
|
-
|
|
1072
|
-
### 4.5 Transaction Operations
|
|
1073
|
-
|
|
1074
|
-
The SDK supports three types of transactions:
|
|
1075
|
-
|
|
1076
|
-
#### Deposits (publicAmount > 0)
|
|
236
|
+
`VeiloRelayerClient` encrypts private transaction requests before sending them
|
|
237
|
+
to the relayer. The request and response types are exported for TypeScript
|
|
238
|
+
autocomplete.
|
|
1077
239
|
|
|
1078
240
|
```ts
|
|
1079
|
-
import {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
amount: 1_000_000_000n, // 1 SOL
|
|
1084
|
-
mintAddress: pubkeyToField(NATIVE_SOL_MINT),
|
|
1085
|
-
keypair: utxoKeypair,
|
|
1086
|
-
});
|
|
1087
|
-
|
|
1088
|
-
// Zero inputs for deposit
|
|
1089
|
-
const input1 = createOwnedZeroUTXO(pubkeyToField(NATIVE_SOL_MINT), utxoKeypair);
|
|
1090
|
-
const input2 = createOwnedZeroUTXO(pubkeyToField(NATIVE_SOL_MINT), utxoKeypair);
|
|
1091
|
-
const output2 = createOwnedZeroUTXO(
|
|
1092
|
-
pubkeyToField(NATIVE_SOL_MINT),
|
|
1093
|
-
utxoKeypair,
|
|
1094
|
-
);
|
|
241
|
+
import {
|
|
242
|
+
VeiloRelayerClient,
|
|
243
|
+
type WithdrawRequest,
|
|
244
|
+
} from "@veilo/sdk-core/relayer";
|
|
1095
245
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
inputTreeId: 0,
|
|
1101
|
-
outputTreeId: 0,
|
|
1102
|
-
root: tree.root(),
|
|
1103
|
-
publicAmount: 1_000_000_000n, // Positive = deposit
|
|
1104
|
-
inputs: [input1, input2],
|
|
1105
|
-
outputs: [outputUtxo, output2],
|
|
1106
|
-
recipient: depositorKeypair.publicKey,
|
|
1107
|
-
fee: 0n,
|
|
1108
|
-
refund: 0n,
|
|
1109
|
-
proof: mockProof,
|
|
246
|
+
const relayer = new VeiloRelayerClient({
|
|
247
|
+
apiKey: process.env.VEILO_RELAYER_KEY!,
|
|
248
|
+
relayerPublicKey: process.env.VEILO_RELAYER_PUBLIC_KEY!,
|
|
249
|
+
authToken: process.env.VEILO_AUTH_TOKEN,
|
|
1110
250
|
});
|
|
1111
251
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
252
|
+
async function submitWithdrawal(request: WithdrawRequest) {
|
|
253
|
+
return relayer.submitWithdraw(request);
|
|
254
|
+
}
|
|
1115
255
|
```
|
|
1116
256
|
|
|
1117
|
-
|
|
257
|
+
The same client also provides account authentication, encrypted note storage,
|
|
258
|
+
Merkle tree reads, private transfers, and private swaps.
|
|
1118
259
|
|
|
1119
|
-
|
|
1120
|
-
import { withdraw } from "@veilo/sdk-core";
|
|
1121
|
-
|
|
1122
|
-
// Prepare input with Merkle path
|
|
1123
|
-
const input1: InputUTXO = {
|
|
1124
|
-
...ownedUtxo1,
|
|
1125
|
-
pathIndex: 0,
|
|
1126
|
-
pathElements: tree.path(0).pathElements,
|
|
1127
|
-
};
|
|
1128
|
-
|
|
1129
|
-
const zeroInput2: InputUTXO = {
|
|
1130
|
-
...createOwnedZeroUTXO(pubkeyToField(NATIVE_SOL_MINT), utxoKeypair),
|
|
1131
|
-
pathIndex: 0,
|
|
1132
|
-
pathElements: tree.path(0).pathElements,
|
|
1133
|
-
};
|
|
1134
|
-
|
|
1135
|
-
// Zero outputs
|
|
1136
|
-
const output1 = createOwnedZeroUTXO(
|
|
1137
|
-
pubkeyToField(NATIVE_SOL_MINT),
|
|
1138
|
-
utxoKeypair,
|
|
1139
|
-
);
|
|
1140
|
-
const output2 = createOwnedZeroUTXO(
|
|
1141
|
-
pubkeyToField(NATIVE_SOL_MINT),
|
|
1142
|
-
utxoKeypair,
|
|
1143
|
-
);
|
|
260
|
+
### Use the direct helpers
|
|
1144
261
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
relayer: relayerKeypair,
|
|
1148
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
1149
|
-
inputTreeId: 0,
|
|
1150
|
-
outputTreeId: 0,
|
|
1151
|
-
root: tree.root(),
|
|
1152
|
-
publicAmount: -900_000_000n, // Negative = withdrawal (0.9 SOL)
|
|
1153
|
-
inputs: [input1, zeroInput2],
|
|
1154
|
-
outputs: [output1, output2],
|
|
1155
|
-
recipient: recipientKeypair.publicKey,
|
|
1156
|
-
fee: 100_000_000n, // 0.1 SOL to relayer
|
|
1157
|
-
refund: 0n,
|
|
1158
|
-
proof,
|
|
1159
|
-
});
|
|
1160
|
-
```
|
|
1161
|
-
|
|
1162
|
-
#### Private Transfers (publicAmount = 0)
|
|
262
|
+
Direct helpers are intended for applications that already maintain Veilo note
|
|
263
|
+
and Merkle tree state and can generate proofs.
|
|
1163
264
|
|
|
1164
265
|
```ts
|
|
1165
266
|
import {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
267
|
+
NATIVE_SOL_MINT,
|
|
268
|
+
createTransactionProver,
|
|
269
|
+
createVeiloProgram,
|
|
270
|
+
deposit,
|
|
1169
271
|
} from "@veilo/sdk-core";
|
|
1170
272
|
|
|
1171
|
-
|
|
1172
|
-
const
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
privateKey: recipientKeypair.privateKey,
|
|
1176
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
273
|
+
const program = createVeiloProgram(connection, anchorWallet);
|
|
274
|
+
const proofBuilder = createTransactionProver({
|
|
275
|
+
wasmPath: "/circuits/transaction.wasm",
|
|
276
|
+
zkeyPath: "/circuits/transaction_final.zkey",
|
|
1177
277
|
});
|
|
1178
278
|
|
|
1179
|
-
await
|
|
279
|
+
const built = await deposit({
|
|
1180
280
|
program,
|
|
1181
|
-
|
|
281
|
+
depositor: { publicKey: wallet.publicKey },
|
|
1182
282
|
mintAddress: NATIVE_SOL_MINT,
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
recipient: relayerKeypair.publicKey,
|
|
1190
|
-
fee: 0n,
|
|
1191
|
-
refund: 0n,
|
|
1192
|
-
proof,
|
|
283
|
+
amount: 1_000_000_000n,
|
|
284
|
+
recipientPubkey: veiloOwnerPublicKey,
|
|
285
|
+
noteRecipientWallet: wallet.publicKey,
|
|
286
|
+
tree,
|
|
287
|
+
proofBuilder,
|
|
288
|
+
treeId: 0,
|
|
1193
289
|
});
|
|
1194
290
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
291
|
+
const signed = await wallet.signTransaction(built.transaction);
|
|
292
|
+
const signature = await connection.sendRawTransaction(signed.serialize());
|
|
293
|
+
await connection.confirmTransaction(signature, "confirmed");
|
|
294
|
+
|
|
295
|
+
// Update the local tree only after on-chain confirmation.
|
|
296
|
+
const receipt = built.commit();
|
|
1198
297
|
```
|
|
1199
298
|
|
|
1200
|
-
|
|
299
|
+
`withdraw()` and `privateTransfer()` accept two spendable input notes, build the
|
|
300
|
+
proof, submit through the supplied relayer signer, and return the resulting
|
|
301
|
+
change or output notes. Important rules are enforced by the SDK:
|
|
1201
302
|
|
|
1202
|
-
|
|
303
|
+
- withdrawal amounts must be positive and fit within the selected notes;
|
|
304
|
+
- private-transfer outputs must equal the total input amount;
|
|
305
|
+
- direct private transfers use a zero public fee;
|
|
306
|
+
- note-recipient wallet keys should be supplied so new notes remain recoverable.
|
|
1203
307
|
|
|
1204
|
-
|
|
1205
|
-
|
|
308
|
+
Private swaps normally use Jupiter versioned transactions and address lookup
|
|
309
|
+
tables. Use `buildPrivateSwapInstructions()` to add Veilo's atomic instructions
|
|
310
|
+
to the exact Jupiter route. Preserve Jupiter's account order and duplicate
|
|
311
|
+
accounts. `transactSwap()` is available when a legacy transaction is sufficient.
|
|
1206
312
|
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
relayer: relayerKeypair,
|
|
1210
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
1211
|
-
inputTreeId: 0,
|
|
1212
|
-
outputTreeId: 0,
|
|
1213
|
-
root: tree.root(),
|
|
1214
|
-
publicAmount: 0n,
|
|
1215
|
-
inputNullifiers: [nullifier1, nullifier2],
|
|
1216
|
-
outputCommitments: [output1.commitment, output2.commitment],
|
|
1217
|
-
extData: {
|
|
1218
|
-
recipient: recipientPubkey,
|
|
1219
|
-
relayer: relayerPubkey,
|
|
1220
|
-
fee: 0n,
|
|
1221
|
-
refund: 0n,
|
|
1222
|
-
claimant: claimantPubkey,
|
|
1223
|
-
},
|
|
1224
|
-
proof,
|
|
1225
|
-
});
|
|
1226
|
-
```
|
|
313
|
+
The low-level `transact()` and `buildRawTransactInstruction()` exports are for
|
|
314
|
+
custom transaction composition. Most applications should use the helpers above.
|
|
1227
315
|
|
|
1228
|
-
|
|
316
|
+
## Important concepts
|
|
1229
317
|
|
|
1230
|
-
###
|
|
318
|
+
### Amounts use base units
|
|
1231
319
|
|
|
1232
|
-
|
|
320
|
+
Amounts are `bigint` values or decimal strings in the token's smallest unit:
|
|
1233
321
|
|
|
1234
322
|
```ts
|
|
1235
|
-
import {
|
|
1236
|
-
prepareTransactionInputs,
|
|
1237
|
-
formatInputsForSnarkjs,
|
|
1238
|
-
computeExtDataHash,
|
|
1239
|
-
encodeSnarkjsProofToTransactionProof,
|
|
1240
|
-
packProofToBytes,
|
|
1241
|
-
type ExtData,
|
|
1242
|
-
type TransactionCircuitInputs,
|
|
1243
|
-
} from "@veilo/sdk-core";
|
|
323
|
+
import { sol } from "@veilo/sdk-core/config";
|
|
1244
324
|
|
|
1245
|
-
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
publicAmount: 1_000_000_000n,
|
|
1249
|
-
extData: {
|
|
1250
|
-
recipient: recipientPubkey,
|
|
1251
|
-
relayer: relayerPubkey,
|
|
1252
|
-
fee: 0n,
|
|
1253
|
-
refund: 0n,
|
|
1254
|
-
claimant: claimantPubkey,
|
|
1255
|
-
},
|
|
1256
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
1257
|
-
inputs: [input1, input2],
|
|
1258
|
-
outputs: [output1, output2],
|
|
1259
|
-
inputTreeId: 0,
|
|
1260
|
-
outputTreeId: 0,
|
|
1261
|
-
});
|
|
325
|
+
const oneSol = sol(1); // 1_000_000_000n lamports
|
|
326
|
+
const fiveUsdc = 5_000_000n; // 5 USDC for a 6-decimal mint
|
|
327
|
+
```
|
|
1262
328
|
|
|
1263
|
-
|
|
1264
|
-
const snarkjsInputs = formatInputsForSnarkjs(circuitInputs);
|
|
329
|
+
Avoid JavaScript floating-point values for token arithmetic.
|
|
1265
330
|
|
|
1266
|
-
|
|
1267
|
-
// const { proof, publicSignals } = await snarkjs.groth16.fullProve(
|
|
1268
|
-
// snarkjsInputs,
|
|
1269
|
-
// wasmPath,
|
|
1270
|
-
// zkeyPath
|
|
1271
|
-
// );
|
|
331
|
+
### A private note is valuable secret data
|
|
1272
332
|
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
333
|
+
A note contains the information needed to locate and spend private funds. Store
|
|
334
|
+
it encrypted, never log it, and never send its unencrypted contents to an
|
|
335
|
+
analytics or application server.
|
|
1276
336
|
|
|
1277
|
-
|
|
337
|
+
For shielding, prefer `resolveShieldOwner()`. It obtains the spending and note
|
|
338
|
+
viewing keys as a matched pair. Supplying unrelated keys can create a note that
|
|
339
|
+
the recipient cannot discover.
|
|
1278
340
|
|
|
1279
|
-
###
|
|
341
|
+
### Confirmation comes before local state updates
|
|
1280
342
|
|
|
1281
|
-
|
|
1282
|
-
|
|
343
|
+
Do not mark notes as spent, insert commitments into a local tree, or persist a
|
|
344
|
+
predicted leaf index until the transaction is confirmed. Use `finalizeShield()`
|
|
345
|
+
for shields and call a deposit's `commit()` callback only after confirmation.
|
|
1283
346
|
|
|
1284
|
-
|
|
1285
|
-
await addRelayer({
|
|
1286
|
-
program,
|
|
1287
|
-
admin: adminKeypair,
|
|
1288
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
1289
|
-
newRelayer: relayerPubkey,
|
|
1290
|
-
});
|
|
347
|
+
### Proof files are separate
|
|
1291
348
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
admin: adminKeypair,
|
|
1296
|
-
mintAddress: NATIVE_SOL_MINT,
|
|
1297
|
-
paused: true,
|
|
1298
|
-
});
|
|
1299
|
-
```
|
|
349
|
+
Circuit `.wasm` and `.zkey` files are intentionally not bundled with the npm
|
|
350
|
+
package because they are large. Provide local paths, byte arrays, or hosted URLs
|
|
351
|
+
to `createTransactionProver()` and `createSwapProver()`.
|
|
1300
352
|
|
|
1301
|
-
|
|
353
|
+
## Error handling
|
|
1302
354
|
|
|
1303
|
-
|
|
355
|
+
Shield and Cloak errors include stable fields that applications can use to show
|
|
356
|
+
useful recovery actions.
|
|
1304
357
|
|
|
1305
358
|
```ts
|
|
1306
359
|
import {
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
poseidon2,
|
|
1310
|
-
poseidon3,
|
|
1311
|
-
poseidon4,
|
|
1312
|
-
pubkeyToField,
|
|
360
|
+
CloakApiError,
|
|
361
|
+
mapShieldError,
|
|
1313
362
|
} from "@veilo/sdk-core";
|
|
1314
363
|
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
const
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
364
|
+
try {
|
|
365
|
+
// Build or submit a Veilo operation.
|
|
366
|
+
} catch (error) {
|
|
367
|
+
if (error instanceof CloakApiError) {
|
|
368
|
+
console.error(error.code, error.status, error.message);
|
|
369
|
+
} else {
|
|
370
|
+
const shieldError = mapShieldError(error);
|
|
371
|
+
console.error(shieldError.code, shieldError.message);
|
|
372
|
+
// retryable is `rebuild`, `reshield`, or `none`.
|
|
373
|
+
console.log(shieldError.retryable);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
1326
376
|
```
|
|
1327
377
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
### Transaction Model
|
|
378
|
+
When handling Cloak separately, `CloakApiError` also exposes actionable values
|
|
379
|
+
such as `min`, `max`, `field`, `maxBps`, and `retryAfter` when the API returns
|
|
380
|
+
them.
|
|
1333
381
|
|
|
1334
|
-
|
|
382
|
+
## Package entry points
|
|
1335
383
|
|
|
1336
|
-
|
|
1337
|
-
2. **Outputs**: 2 UTXOs (can be zero for withdrawals)
|
|
1338
|
-
3. **Public Amount**: Net change (positive = deposit, negative = withdrawal, zero = private transfer)
|
|
1339
|
-
|
|
1340
|
-
Each transaction:
|
|
1341
|
-
|
|
1342
|
-
- Consumes 2 input UTXOs (proven via Merkle paths)
|
|
1343
|
-
- Creates 2 output UTXOs (commitments added to tree)
|
|
1344
|
-
- Generates 2 nullifiers (prevents double-spending)
|
|
1345
|
-
- Optionally transfers funds in/out of the pool
|
|
1346
|
-
|
|
1347
|
-
### Privacy Guarantees
|
|
1348
|
-
|
|
1349
|
-
- **Commitment hiding**: Amount, owner, and blinding factor are hidden via Poseidon hash
|
|
1350
|
-
- **Nullifier uniqueness**: Each UTXO can only be spent once
|
|
1351
|
-
- **Unlinkability**: No public link between inputs and outputs
|
|
1352
|
-
- **Zero-knowledge proofs**: Transactions proven valid without revealing private data
|
|
1353
|
-
|
|
1354
|
-
### Multi-Tree Support
|
|
1355
|
-
|
|
1356
|
-
The protocol supports multiple concurrent Merkle trees per pool:
|
|
1357
|
-
|
|
1358
|
-
- Improves scalability by reducing tree depth
|
|
1359
|
-
- Allows parallel insertions
|
|
1360
|
-
- Each tree has independent state
|
|
1361
|
-
|
|
1362
|
-
### Constants
|
|
384
|
+
Import from the package root for convenience or use a focused entry point:
|
|
1363
385
|
|
|
1364
386
|
```ts
|
|
1365
|
-
import {
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
} from "@veilo/sdk-core/config";
|
|
1372
|
-
|
|
1373
|
-
import { BN254_FR_MODULUS } from "@veilo/sdk-core";
|
|
387
|
+
import { shield } from "@veilo/sdk-core";
|
|
388
|
+
import { getPoolPdas } from "@veilo/sdk-core/accounts";
|
|
389
|
+
import { createUTXO } from "@veilo/sdk-core/notes";
|
|
390
|
+
import { deposit, withdraw } from "@veilo/sdk-core/transactions";
|
|
391
|
+
import { VeiloRelayerClient } from "@veilo/sdk-core/relayer";
|
|
392
|
+
import { VeiloCloakClient } from "@veilo/sdk-core/cloak";
|
|
1374
393
|
```
|
|
1375
394
|
|
|
1376
|
-
|
|
395
|
+
Available focused entry points:
|
|
1377
396
|
|
|
1378
|
-
|
|
397
|
+
- `@veilo/sdk-core/accounts`
|
|
398
|
+
- `@veilo/sdk-core/cloak`
|
|
399
|
+
- `@veilo/sdk-core/config`
|
|
400
|
+
- `@veilo/sdk-core/notes`
|
|
401
|
+
- `@veilo/sdk-core/poseidon`
|
|
402
|
+
- `@veilo/sdk-core/proof`
|
|
403
|
+
- `@veilo/sdk-core/prover`
|
|
404
|
+
- `@veilo/sdk-core/relayer`
|
|
405
|
+
- `@veilo/sdk-core/shield`
|
|
406
|
+
- `@veilo/sdk-core/transactions`
|
|
1379
407
|
|
|
1380
|
-
|
|
1381
|
-
import type {
|
|
1382
|
-
// UTXO types
|
|
1383
|
-
Keypair,
|
|
1384
|
-
UTXO,
|
|
1385
|
-
SerializedUTXO,
|
|
1386
|
-
InputUTXO,
|
|
1387
|
-
|
|
1388
|
-
// Proof types
|
|
1389
|
-
ExtData,
|
|
1390
|
-
TransactionCircuitInputs,
|
|
1391
|
-
TransactionProofStruct,
|
|
1392
|
-
RawProof,
|
|
1393
|
-
TransactionProofBuilder,
|
|
1394
|
-
|
|
1395
|
-
// Merkle types
|
|
1396
|
-
MerklePath,
|
|
1397
|
-
CircuitMerklePath,
|
|
1398
|
-
|
|
1399
|
-
// Config types
|
|
1400
|
-
PoolInitConfig,
|
|
1401
|
-
PrivacyConfigAccount,
|
|
1402
|
-
GlobalConfigAccount,
|
|
1403
|
-
} from "@veilo/sdk-core";
|
|
1404
|
-
```
|
|
1405
|
-
|
|
1406
|
-
### SPL Token Support
|
|
408
|
+
## Advanced building blocks
|
|
1407
409
|
|
|
1408
|
-
The
|
|
410
|
+
The root package also exports tools for teams building their own Veilo wallet
|
|
411
|
+
or relayer:
|
|
1409
412
|
|
|
1410
|
-
|
|
1411
|
-
|
|
413
|
+
- account and PDA queries;
|
|
414
|
+
- UTXO creation, ownership, encryption, and recovery;
|
|
415
|
+
- Merkle tree reconstruction from on-chain events;
|
|
416
|
+
- transaction and swap witness preparation;
|
|
417
|
+
- Poseidon hashing helpers;
|
|
418
|
+
- pool initialization and administration;
|
|
419
|
+
- raw IDL-correct transaction instruction builders.
|
|
1412
420
|
|
|
1413
|
-
|
|
1414
|
-
|
|
421
|
+
These APIs are fully typed. Use their TypeScript definitions as the source of
|
|
422
|
+
truth for required inputs.
|
|
1415
423
|
|
|
1416
|
-
|
|
1417
|
-
const usdcMint = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
1418
|
-
|
|
1419
|
-
// Initialize pool for SPL token
|
|
1420
|
-
await initializePool({
|
|
1421
|
-
program,
|
|
1422
|
-
payer: adminKeypair,
|
|
1423
|
-
admin: adminKeypair,
|
|
1424
|
-
mintAddress: usdcMint, // Use SPL token mint
|
|
1425
|
-
minDepositAmount: 1_000_000n, // 1 USDC (6 decimals)
|
|
1426
|
-
// ... other params
|
|
1427
|
-
});
|
|
1428
|
-
```
|
|
1429
|
-
|
|
1430
|
-
When using SPL tokens, the SDK automatically handles associated token accounts.
|
|
1431
|
-
|
|
1432
|
-
---
|
|
1433
|
-
|
|
1434
|
-
## 6. Development
|
|
1435
|
-
|
|
1436
|
-
### Environment Variables
|
|
424
|
+
## Development
|
|
1437
425
|
|
|
1438
426
|
```bash
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
```
|
|
1442
|
-
|
|
1443
|
-
---
|
|
427
|
+
# Build CommonJS, ESM, and declaration outputs
|
|
428
|
+
npm run build
|
|
1444
429
|
|
|
1445
|
-
|
|
430
|
+
# Run deterministic unit and proof tests
|
|
431
|
+
npm test
|
|
1446
432
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
- **Development status**: Active development, APIs may change
|
|
433
|
+
# Run opt-in live Devnet integration tests
|
|
434
|
+
npm run test:integration
|
|
1450
435
|
|
|
1451
|
-
|
|
436
|
+
# Check module boundaries for dependency cycles
|
|
437
|
+
npm run check:cycles
|
|
438
|
+
```
|
|
1452
439
|
|
|
1453
|
-
##
|
|
440
|
+
## Support
|
|
1454
441
|
|
|
1455
|
-
-
|
|
1456
|
-
-
|
|
1457
|
-
- **Poseidon Hash**: https://www.poseidon-hash.info/
|
|
442
|
+
- [Repository](https://github.com/VeiloSolana/veilo-sdk)
|
|
443
|
+
- [Issue tracker](https://github.com/VeiloSolana/veilo-sdk/issues)
|
|
1458
444
|
|
|
1459
|
-
|
|
445
|
+
When reporting a problem, include the SDK version, runtime, Solana cluster, and
|
|
446
|
+
the error's `code` and `status` or `programCode` where available. Never include
|
|
447
|
+
private notes, wallet secret keys, API keys, or authentication tokens.
|
|
1460
448
|
|
|
1461
449
|
## License
|
|
1462
450
|
|
|
1463
|
-
ISC
|
|
451
|
+
[ISC](./LICENSE)
|