veilix-sdk 0.0.10 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -145
- package/dist/VeilixSDK-CGbGpth9.d.cts +781 -0
- package/dist/VeilixSDK-D1hKisoi.d.ts +781 -0
- package/dist/circuits/paths.cjs +4 -4
- package/dist/circuits/paths.cjs.map +1 -1
- package/dist/circuits/paths.d.cts +2 -2
- package/dist/circuits/paths.d.ts +2 -2
- package/dist/circuits/paths.js +4 -4
- package/dist/circuits/paths.js.map +1 -1
- package/dist/circuits/withdraw.wasm +0 -0
- package/dist/circuits/withdraw.zkey +0 -0
- package/dist/{constants-sO9UKB9l.d.cts → constants-C-u6nmCv.d.cts} +2 -2
- package/dist/{constants-sO9UKB9l.d.ts → constants-C-u6nmCv.d.ts} +2 -2
- package/dist/index.cjs +3207 -2494
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +3197 -2506
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +3190 -2496
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +4 -2
- package/dist/react/index.d.ts +4 -2
- package/dist/react/index.js +3187 -2494
- package/dist/react/index.js.map +1 -1
- package/dist/vite/index.cjs.map +1 -1
- package/dist/vite/index.js.map +1 -1
- package/package.json +3 -1
- package/dist/VeilixSDK-BmB790UK.d.ts +0 -386
- package/dist/VeilixSDK-DgXMu4lI.d.cts +0 -386
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript SDK for interacting with the Veilix privacy protocol on Solana — deposits, withdrawals, private transfers, and fee quotes.
|
|
4
4
|
|
|
5
|
+
Veilix uses a UTXO note model: a deposit can be **any amount** (up to the pool's per-deposit cap), and a withdrawal can take the whole note or only part of it — the remainder comes back as a new *change note*.
|
|
6
|
+
|
|
5
7
|
**Third-party partners** integrating Private Send into their own website or app (quote → wallet sign → deposit → `/submit`): see [`docs/partner-private-send.md`](./docs/partner-private-send.md).
|
|
6
8
|
|
|
7
9
|
## Installation
|
|
@@ -18,10 +20,10 @@ npm install @solana/wallet-adapter-react react
|
|
|
18
20
|
|
|
19
21
|
## Prerequisites
|
|
20
22
|
|
|
21
|
-
- A Solana wallet (`Keypair` for backend/scripts, or a wallet adapter with `signMessage` / `signAllTransactions` for frontend)
|
|
23
|
+
- A Solana wallet (`Keypair` for backend/scripts, or a wallet adapter with `signMessage` / `signTransaction` / `signAllTransactions` for frontend)
|
|
22
24
|
- An RPC endpoint or existing `@solana/web3.js` `Connection`
|
|
23
25
|
|
|
24
|
-
Supported networks: `mainnet` and `devnet` (
|
|
26
|
+
Supported networks: `mainnet` and `devnet` (set via `network`).
|
|
25
27
|
|
|
26
28
|
---
|
|
27
29
|
|
|
@@ -29,244 +31,216 @@ Supported networks: `mainnet` and `devnet` (inferred from the RPC URL, or set ex
|
|
|
29
31
|
|
|
30
32
|
Create one SDK instance per configuration (network, RPC, wallet). Initialization loads active relayers for the target network.
|
|
31
33
|
|
|
32
|
-
```ts
|
|
33
|
-
import { VeilixSDK
|
|
34
|
+
```ts
|
|
35
|
+
import { VeilixSDK } from "veilix-sdk";
|
|
34
36
|
|
|
35
|
-
VeilixSDK.create({
|
|
36
|
-
rpcEndpoint: RPC_URL,
|
|
37
|
+
const sdk = await VeilixSDK.create({
|
|
38
|
+
rpcEndpoint: RPC_URL, // or `connection`
|
|
37
39
|
wallet,
|
|
38
|
-
network:
|
|
39
|
-
})
|
|
40
|
-
.then((sdk) => {
|
|
41
|
-
...
|
|
42
|
-
})
|
|
40
|
+
network: "mainnet",
|
|
41
|
+
});
|
|
43
42
|
```
|
|
44
43
|
|
|
45
44
|
### Init options
|
|
46
45
|
|
|
47
46
|
| Option | Required | Description |
|
|
48
47
|
|--------|----------|-------------|
|
|
49
|
-
| `wallet` | yes | Anchor-compatible wallet (`Keypair` or wallet adapter) |
|
|
50
|
-
| `rpcEndpoint` |
|
|
51
|
-
| `network` | yes | `"mainnet"` or `"devnet"`
|
|
48
|
+
| `wallet` | yes | Anchor-compatible wallet (`Keypair` wrapper or wallet adapter) |
|
|
49
|
+
| `rpcEndpoint` / `connection` | one of | Solana JSON-RPC URL, or an existing `Connection` |
|
|
50
|
+
| `network` | yes | `"mainnet"` or `"devnet"` |
|
|
51
|
+
| `circuitPathsBase` | no | Self-hosted location of `withdraw.wasm` / `withdraw.zkey` |
|
|
52
|
+
| `indexerUrl` | no | Indexer override (defaults to the Veilix indexer of `network`) |
|
|
53
|
+
| `riskApiUrl` | no | Address-risk API override |
|
|
52
54
|
|
|
53
55
|
After creation, inspect runtime config via `sdk.config` or helpers like `sdk.getNetwork()`, `sdk.relayers`, and `sdk.getTokenMints()`.
|
|
54
56
|
|
|
55
57
|
---
|
|
56
58
|
|
|
57
|
-
##
|
|
59
|
+
## Notes
|
|
60
|
+
|
|
61
|
+
A note is the secret needed to spend deposited funds:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
vx2-<amountHex>-<privateKeyHex>-<blindingHex>[-<mint>]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The mint suffix is omitted for SOL. Anyone holding the note can withdraw it, so store it safely. Notes from the previous (fixed-denomination) pool are not compatible; `sdk.isLegacyNote(note)` detects them.
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
```ts
|
|
70
|
+
const parsed = sdk.parseSecretNote(note); // { amount, mint, commitment, commitmentHex, ... }
|
|
71
|
+
const status = await sdk.getNoteStatus(note); // { deposited, index, spent, spentIn, ... }
|
|
72
|
+
```
|
|
60
73
|
|
|
61
|
-
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## `getEncryptionKey`
|
|
77
|
+
|
|
78
|
+
Derives a note-encryption key from a wallet signature and stores it on the SDK instance (`sdk.encryptKey`). The wallet signs the message `veilix:notes:v1`. Accepts a backend `Keypair` or a frontend wallet adapter with `signMessage`.
|
|
62
79
|
|
|
63
80
|
```ts
|
|
64
81
|
await sdk.getEncryptionKey(wallet);
|
|
65
|
-
// sdk.encryptKey is now set
|
|
66
82
|
```
|
|
67
83
|
|
|
68
|
-
The key is used to
|
|
84
|
+
The key is used to:
|
|
69
85
|
|
|
70
|
-
|
|
86
|
+
- seal a deposit's note into its on-chain encrypted output (`onChainBackup: true`), and
|
|
87
|
+
- seal the change note of a partial withdrawal,
|
|
71
88
|
|
|
72
|
-
|
|
89
|
+
so that `sdk.scanOwnedNotes()` can recover every unspent note of the wallet later.
|
|
90
|
+
|
|
91
|
+
---
|
|
73
92
|
|
|
74
|
-
|
|
93
|
+
## Deposit
|
|
75
94
|
|
|
76
|
-
### 1. Generate
|
|
95
|
+
### 1. Generate a note
|
|
77
96
|
|
|
78
97
|
```ts
|
|
79
|
-
// 1 SOL
|
|
80
|
-
const { note } = sdk.generateDepositParams(
|
|
98
|
+
// 1.5 SOL (lamports)
|
|
99
|
+
const { note } = sdk.generateDepositParams(1_500_000_000n, null);
|
|
81
100
|
|
|
82
|
-
// SPL token
|
|
101
|
+
// SPL token — pass the token mint and base units
|
|
83
102
|
const usdcMint = sdk.getTokenMint("USDC");
|
|
84
|
-
const { note: usdcNote } = sdk.generateDepositParams(
|
|
103
|
+
const { note: usdcNote } = sdk.generateDepositParams(
|
|
104
|
+
sdk.parseAmountToBaseUnits("25.5", 6),
|
|
105
|
+
usdcMint
|
|
106
|
+
);
|
|
85
107
|
```
|
|
86
108
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
### 2. Build the transaction
|
|
109
|
+
### 2. Build, sign and send
|
|
90
110
|
|
|
91
111
|
```ts
|
|
92
112
|
await sdk.getEncryptionKey(wallet); // required when onChainBackup is true
|
|
93
113
|
|
|
94
|
-
const
|
|
114
|
+
const tx = await sdk.buildDepositTx({
|
|
95
115
|
senderPublicKey: wallet.publicKey,
|
|
96
116
|
note,
|
|
97
|
-
onChainBackup: true,
|
|
98
|
-
computeUnitPrice: 50_000,
|
|
99
|
-
tempSigner: tempSignerPublicKey // to prevent ix assertion in browser
|
|
117
|
+
onChainBackup: true, // recover the note later with scanOwnedNotes (recommended)
|
|
118
|
+
computeUnitPrice: 50_000, // optional priority fee (micro-lamports / CU)
|
|
100
119
|
});
|
|
120
|
+
|
|
121
|
+
const signed = await wallet.signTransaction(tx); // VersionedTransaction
|
|
122
|
+
const signature = await connection.sendRawTransaction(signed.serialize());
|
|
101
123
|
```
|
|
102
124
|
|
|
103
|
-
|
|
125
|
+
`buildDepositTx` generates the deposit ZK proof (a few seconds) and returns an unsigned `VersionedTransaction`. **Save the `note` before sending** — it is required to withdraw.
|
|
104
126
|
|
|
105
127
|
| Parameter | Description |
|
|
106
128
|
|-----------|-------------|
|
|
107
129
|
| `senderPublicKey` | Depositor's public key |
|
|
108
130
|
| `note` | Secret note from `generateDepositParams` |
|
|
109
|
-
| `onChainBackup` |
|
|
110
|
-
| `computeUnitPrice` | Priority fee in micro-lamports (default `
|
|
131
|
+
| `onChainBackup` | Seal the note into the deposit's encrypted output (requires `getEncryptionKey`) |
|
|
132
|
+
| `computeUnitPrice` | Priority fee in micro-lamports (default `5000`) |
|
|
133
|
+
| `computeUnitLimit` | Compute unit limit override |
|
|
134
|
+
|
|
135
|
+
The pool's per-deposit cap is available via `(await sdk.fetchTreeAccount(mint)).maxDepositAmount`.
|
|
111
136
|
|
|
112
137
|
---
|
|
113
138
|
|
|
114
139
|
## `withdraw`
|
|
115
140
|
|
|
116
|
-
Withdraws
|
|
141
|
+
Withdraws a note (or part of it) to a recipient through a relayer. The SDK:
|
|
117
142
|
|
|
118
143
|
1. Validates the recipient against the risk API
|
|
119
|
-
2.
|
|
120
|
-
3.
|
|
121
|
-
4. Submits the proof to a relayer (
|
|
144
|
+
2. Locates the note in the indexer and checks it is unspent
|
|
145
|
+
3. Rebuilds the Merkle tree and generates the ZK proof
|
|
146
|
+
4. Submits the proof to a relayer (random, by index, or by URL)
|
|
122
147
|
5. Polls until the relayer confirms the on-chain transaction
|
|
123
148
|
|
|
124
149
|
```ts
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
// Full note
|
|
151
|
+
const result = await sdk.withdraw({ note, recipient: "RecipientPubkey..." });
|
|
152
|
+
|
|
153
|
+
// Partial: withdraw 0.4 SOL, keep the rest as a change note
|
|
154
|
+
const partial = await sdk.withdraw({
|
|
155
|
+
note,
|
|
156
|
+
recipient: "RecipientPubkey...",
|
|
157
|
+
amount: 400_000_000n,
|
|
158
|
+
});
|
|
159
|
+
console.log(partial.changeNote); // save it — it holds the remaining funds
|
|
131
160
|
|
|
132
|
-
console.log(result.
|
|
133
|
-
console.log(result.
|
|
161
|
+
console.log(result.status); // "success" | "failed"
|
|
162
|
+
console.log(result.txHash); // withdraw transaction signature
|
|
163
|
+
console.log(result.fee); // total fee in base units (relayer + platform)
|
|
134
164
|
```
|
|
135
165
|
|
|
136
166
|
| Parameter | Description |
|
|
137
167
|
|-----------|-------------|
|
|
138
|
-
| `note` | Secret note
|
|
168
|
+
| `note` | Secret note to spend |
|
|
139
169
|
| `recipient` | Recipient public key (`PublicKey` or base58 string) |
|
|
140
|
-
| `
|
|
170
|
+
| `amount` | Optional base-unit amount before fees; defaults to the full note |
|
|
171
|
+
| `relayerUrl` | Optional relayer URL (otherwise `relayerIdx` or random) |
|
|
172
|
+
| second argument `relayerIdx` | Optional index into `sdk.relayers` |
|
|
173
|
+
|
|
174
|
+
The recipient receives `amount - fee`. When `sdk.encryptKey` is set, the change note is also sealed on-chain so `scanOwnedNotes` can find it.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## `scanOwnedNotes`
|
|
179
|
+
|
|
180
|
+
Recovers the wallet's notes by trial-decrypting the pool's encrypted outputs with `sdk.encryptKey`:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
await sdk.getEncryptionKey(wallet);
|
|
184
|
+
const notes = await sdk.scanOwnedNotes(); // unspent notes, SOL + configured tokens
|
|
185
|
+
// options: { mints: [null, usdcMint], includeSpent: true }
|
|
186
|
+
```
|
|
141
187
|
|
|
142
|
-
|
|
188
|
+
Each entry is a `NoteStatus` with the re-encoded `note`, `amount`, `mint`, `index` and spend state.
|
|
143
189
|
|
|
144
190
|
---
|
|
145
191
|
|
|
146
192
|
## `veilixTransfer`
|
|
147
193
|
|
|
148
|
-
End-to-end private transfer:
|
|
194
|
+
End-to-end private transfer: deposits one note per item, then withdraws each note to its recipient via the indexer `/submit` queue. Handles proving, signing, sending, and settlement.
|
|
149
195
|
|
|
150
|
-
**
|
|
196
|
+
**Keep the window open until it resolves.**
|
|
151
197
|
|
|
152
198
|
```ts
|
|
153
199
|
import { PublicKey } from "@solana/web3.js";
|
|
154
200
|
|
|
155
201
|
const result = await sdk.veilixTransfer(
|
|
156
202
|
[
|
|
157
|
-
{
|
|
158
|
-
|
|
159
|
-
amount: "25", // human-readable amount
|
|
160
|
-
recipient: new PublicKey("RecipientPubkey..."),
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
mint: new PublicKey(sdk.getTokenMints().Solana),
|
|
164
|
-
amount: "1.5",
|
|
165
|
-
recipient: new PublicKey("AnotherRecipient..."),
|
|
166
|
-
},
|
|
203
|
+
{ mint: new PublicKey(sdk.getTokenMint("USDC")), amount: "25", recipient: new PublicKey("Recipient...") },
|
|
204
|
+
{ mint: new PublicKey(sdk.getTokenMints().Solana), amount: "1.5", recipient: new PublicKey("Another...") },
|
|
167
205
|
],
|
|
206
|
+
{ uniqueRelayer: false, onChainBackup: true, downloadNotes: true }
|
|
168
207
|
);
|
|
169
208
|
|
|
170
209
|
if (result.error) {
|
|
171
210
|
console.log("Deposit failures:", result.depositFailed);
|
|
172
|
-
console.log("Withdraw failures:", result.withdrawFailed);
|
|
211
|
+
console.log("Withdraw failures:", result.withdrawFailed); // include the note, still spendable
|
|
173
212
|
}
|
|
174
213
|
```
|
|
175
214
|
|
|
176
|
-
|
|
|
177
|
-
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
215
|
+
| Option | Default | Description |
|
|
216
|
+
|--------|---------|-------------|
|
|
217
|
+
| `uniqueRelayer` | `false` | Use one random relayer for every withdraw |
|
|
218
|
+
| `onChainBackup` | `true` when `encryptKey` is set | Seal each note into its deposit |
|
|
219
|
+
| `downloadNotes` | `true` | Download the notes as CSV (browser) before sending |
|
|
181
220
|
|
|
182
|
-
|
|
221
|
+
Partial failures are reported without throwing; `result.notes` lists every note created.
|
|
183
222
|
|
|
184
223
|
---
|
|
185
224
|
|
|
186
225
|
## `getQuote`
|
|
187
226
|
|
|
188
|
-
Fetches a withdraw fee quote from the
|
|
227
|
+
Fetches a withdraw fee quote from the indexer.
|
|
189
228
|
|
|
190
229
|
```ts
|
|
191
230
|
const { quote } = await sdk.getQuote({
|
|
192
|
-
amount: 1.5,
|
|
193
|
-
|
|
194
|
-
recipient: "
|
|
195
|
-
asset: "SOL", // optional — default "SOL"
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
console.log(quote.recipientAmount); // amount recipient receives after fees
|
|
199
|
-
console.log(quote.totalRelayerFee);
|
|
200
|
-
console.log(quote.etaSeconds);
|
|
201
|
-
console.log(quote.splits); // per-denomination breakdown
|
|
202
|
-
console.log(quote.platformFee); // platform fee (added by SDK)
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
| Parameter | Description |
|
|
206
|
-
|-----------|-------------|
|
|
207
|
-
| `amount` | Human-readable transfer/withdraw amount |
|
|
208
|
-
| `amountLamports` | Amount in smallest token units |
|
|
209
|
-
| `recipient` | Intended withdrawal recipient |
|
|
210
|
-
| `asset` | Indexer asset label (default `"SOL"`) |
|
|
211
|
-
| `network` | Optional cluster override |
|
|
212
|
-
|
|
213
|
-
`getQuote` is also exported as a standalone function but requires an initialized SDK context.
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## Typical flows
|
|
218
|
-
|
|
219
|
-
### Deposit and withdraw
|
|
220
|
-
|
|
221
|
-
```ts
|
|
222
|
-
const sdk = await VeilixSDK.create({ rpcEndpoint, wallet, network: "mainnet" });
|
|
223
|
-
|
|
224
|
-
await sdk.getEncryptionKey(wallet);
|
|
225
|
-
|
|
226
|
-
const { note } = sdk.generateDepositParams(1_000_000_000n, null);
|
|
227
|
-
const { tx } = await sdk.buildDepositTx({
|
|
228
|
-
senderPublicKey: wallet.publicKey,
|
|
229
|
-
note,
|
|
230
|
-
onChainBackup: true,
|
|
231
|
+
amount: "1.5", // or amountRaw: "1500000000"
|
|
232
|
+
asset: "SOL", // "SOL" or a token mint
|
|
233
|
+
recipient: "Recipient...",
|
|
231
234
|
});
|
|
232
235
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const { txHash } = await sdk.withdraw({
|
|
236
|
-
note,
|
|
237
|
-
recipient: "RecipientPubkey...",
|
|
238
|
-
});
|
|
236
|
+
console.log(quote.recipientAmount, quote.fee, quote.relayerFee, quote.platformFee);
|
|
237
|
+
console.log(quote.relayer.url, quote.etaSeconds);
|
|
239
238
|
```
|
|
240
239
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
```ts
|
|
244
|
-
const { quote } = await sdk.getQuote({
|
|
245
|
-
amount: 1,
|
|
246
|
-
amountLamports: 1_000_000_000,
|
|
247
|
-
recipient: "RecipientPubkey...",
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
console.log(`Recipient receives ~${quote.recipientAmount} SOL`);
|
|
251
|
-
|
|
252
|
-
await sdk.withdraw({ note, recipient: "RecipientPubkey..." });
|
|
253
|
-
```
|
|
240
|
+
For the exact fee the program will enforce, use `sdk.computeWithdrawFee(amount, relayerFeePercent, await sdk.fetchPlatformFeeWallets())`.
|
|
254
241
|
|
|
255
242
|
---
|
|
256
243
|
|
|
257
|
-
##
|
|
258
|
-
|
|
259
|
-
Amounts must decompose exactly into these pool denominations:
|
|
260
|
-
|
|
261
|
-
| Token | Denominations | Mint Address (mainnet) |
|
|
262
|
-
|-------|---------------|---------------|
|
|
263
|
-
| SOL | 0.1, 1, 5, 10, 50, 100, 500 | |
|
|
264
|
-
| USDC | 1, 10, 50, 100, 1000, 10000, 100000, 1000000 | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
|
|
265
|
-
| Veilix | 10000,50000,100000,500000,1000000,10000000 | |
|
|
266
|
-
| Bitcoin | 0.01, 0.05, 0.1, 0.5, 1, 5 | 3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh |
|
|
267
|
-
| Ethereum (coming soon) | 0.1, 1, 10, 50, 100, 500 | 7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs |
|
|
268
|
-
|
|
269
|
-
Use `sdk.getDepositAmounts("Solana")` (or another symbol) to retrieve the list programmatically.
|
|
270
|
-
|
|
271
|
-
---
|
|
244
|
+
## Circuit artifacts
|
|
272
245
|
|
|
246
|
+
In the browser the SDK loads `withdraw.wasm` / `withdraw.zkey` from the pinned CDN (SHA-256 verified) unless `circuitPathsBase` points elsewhere. With Vite, `veilix-sdk/vite` serves them from `node_modules` during development. In Node the files are read from the package's `dist/circuits`.
|