@veilo/sdk-core 0.5.0 → 0.6.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 +237 -19
- package/accounts.d.ts +2 -0
- package/accounts.js +3 -0
- package/cloak.d.ts +2 -0
- package/cloak.js +3 -0
- package/config.d.ts +2 -0
- package/config.js +3 -0
- package/dist/cjs/events/index.d.ts +6 -0
- package/dist/cjs/events/index.js +22 -0
- package/dist/cjs/events/parsing.d.ts +25 -0
- package/dist/cjs/events/parsing.js +158 -0
- package/dist/cjs/events/position.d.ts +26 -0
- package/dist/cjs/events/position.js +53 -0
- package/dist/cjs/events/recovery.d.ts +87 -0
- package/dist/cjs/events/recovery.js +281 -0
- package/dist/cjs/events/scanning.d.ts +35 -0
- package/dist/cjs/events/scanning.js +98 -0
- package/dist/cjs/events/tree.d.ts +27 -0
- package/dist/cjs/events/tree.js +63 -0
- package/dist/cjs/events/types.d.ts +39 -0
- package/dist/cjs/events/types.js +2 -0
- package/dist/cjs/events.d.ts +1 -77
- package/dist/cjs/events.js +6 -154
- package/dist/cjs/identity/encoding.d.ts +9 -0
- package/dist/cjs/identity/encoding.js +85 -0
- package/dist/cjs/identity/index.d.ts +4 -0
- package/dist/cjs/identity/index.js +20 -0
- package/dist/cjs/identity/noteKey.d.ts +33 -0
- package/dist/cjs/identity/noteKey.js +97 -0
- package/dist/cjs/identity/spending.d.ts +18 -0
- package/dist/cjs/identity/spending.js +46 -0
- package/dist/cjs/identity/viewKey.d.ts +38 -0
- package/dist/cjs/identity/viewKey.js +105 -0
- package/dist/cjs/idl/index.d.ts +18 -0
- package/dist/cjs/idl/index.js +24 -0
- package/dist/cjs/idl/privacy_pool.json +9907 -9907
- package/dist/cjs/idl/privacy_pool_legacy.d.ts +5 -0
- package/dist/cjs/idl/privacy_pool_legacy.js +3307 -0
- package/dist/cjs/idl/privacy_pool_legacy.json +2302 -0
- package/dist/cjs/idl/privacy_pool_legacy2.d.ts +5 -0
- package/dist/cjs/idl/privacy_pool_legacy2.js +3397 -0
- package/dist/cjs/idl/privacy_pool_legacy2.json +2376 -0
- package/dist/cjs/index.d.ts +8 -3
- package/dist/cjs/index.js +12 -2
- package/dist/cjs/notes/amount.d.ts +2 -0
- package/dist/cjs/notes/amount.js +21 -0
- package/dist/cjs/notes/index.d.ts +3 -0
- package/dist/cjs/notes/index.js +3 -0
- package/dist/cjs/notes/recovery.d.ts +16 -6
- package/dist/cjs/notes/recovery.js +33 -16
- package/dist/cjs/notes/selection.d.ts +77 -0
- package/dist/cjs/notes/selection.js +193 -0
- package/dist/cjs/notes/spent.d.ts +60 -0
- package/dist/cjs/notes/spent.js +101 -0
- package/dist/cjs/perps/constants.d.ts +16 -0
- package/dist/cjs/perps/constants.js +52 -0
- package/dist/cjs/perps/index.d.ts +5 -0
- package/dist/cjs/perps/index.js +21 -0
- package/dist/cjs/perps/keys.d.ts +16 -0
- package/dist/cjs/perps/keys.js +43 -0
- package/dist/cjs/perps/pdas.d.ts +29 -0
- package/dist/cjs/perps/pdas.js +55 -0
- package/dist/cjs/perps/relayer.d.ts +9 -0
- package/dist/cjs/perps/relayer.js +35 -0
- package/dist/cjs/perps/types.d.ts +126 -0
- package/dist/cjs/perps/types.js +2 -0
- package/dist/cjs/positions/index.d.ts +4 -0
- package/dist/cjs/positions/index.js +20 -0
- package/dist/cjs/positions/keys.d.ts +29 -0
- package/dist/cjs/positions/keys.js +71 -0
- package/dist/cjs/positions/pdas.d.ts +15 -0
- package/dist/cjs/positions/pdas.js +54 -0
- package/dist/cjs/positions/relayer.d.ts +4 -0
- package/dist/cjs/positions/relayer.js +15 -0
- package/dist/cjs/positions/types.d.ts +97 -0
- package/dist/cjs/positions/types.js +2 -0
- package/dist/cjs/predictions/client.d.ts +41 -0
- package/dist/cjs/predictions/client.js +147 -0
- package/dist/cjs/predictions/index.d.ts +5 -0
- package/dist/cjs/predictions/index.js +21 -0
- package/dist/cjs/predictions/keys.d.ts +14 -0
- package/dist/cjs/predictions/keys.js +40 -0
- package/dist/cjs/predictions/pdas.d.ts +6 -0
- package/dist/cjs/predictions/pdas.js +13 -0
- package/dist/cjs/predictions/relayer.d.ts +3 -0
- package/dist/cjs/predictions/relayer.js +11 -0
- package/dist/cjs/predictions/types.d.ts +178 -0
- package/dist/cjs/predictions/types.js +2 -0
- package/dist/cjs/program.d.ts +2 -0
- package/dist/cjs/program.js +8 -7
- package/dist/cjs/prover.d.ts +27 -4
- package/dist/cjs/prover.js +107 -48
- package/dist/cjs/relayer/api.d.ts +31 -0
- package/dist/cjs/relayer/api.js +86 -0
- package/dist/cjs/relayer/client.d.ts +29 -17
- package/dist/cjs/relayer/client.js +72 -17
- package/dist/cjs/relayer/errors.d.ts +1 -1
- package/dist/cjs/relayer/errors.js +1 -1
- package/dist/cjs/relayer/index.d.ts +4 -1
- package/dist/cjs/relayer/index.js +1 -1
- package/dist/cjs/relayer/internal-config.d.ts +36 -0
- package/dist/cjs/relayer/internal-config.js +9 -0
- package/dist/cjs/relayer/internal.d.ts +6 -0
- package/dist/cjs/relayer/internal.js +14 -0
- package/dist/cjs/relayer/transport.d.ts +4 -2
- package/dist/cjs/relayer/transport.js +10 -5
- package/dist/cjs/relayer/types.d.ts +9 -10
- package/dist/cjs/relayer/types.js +1 -1
- package/dist/cjs/shield/owner.js +1 -4
- package/dist/esm/events/index.d.ts +6 -0
- package/dist/esm/events/index.js +6 -0
- package/dist/esm/events/parsing.d.ts +25 -0
- package/dist/esm/events/parsing.js +120 -0
- package/dist/esm/events/position.d.ts +26 -0
- package/dist/esm/events/position.js +48 -0
- package/dist/esm/events/recovery.d.ts +87 -0
- package/dist/esm/events/recovery.js +237 -0
- package/dist/esm/events/scanning.d.ts +35 -0
- package/dist/esm/events/scanning.js +92 -0
- package/dist/esm/events/tree.d.ts +27 -0
- package/dist/esm/events/tree.js +58 -0
- package/dist/esm/events/types.d.ts +39 -0
- package/dist/esm/events/types.js +1 -0
- package/dist/esm/events.d.ts +1 -77
- package/dist/esm/events.js +3 -129
- package/dist/esm/identity/encoding.d.ts +9 -0
- package/dist/esm/identity/encoding.js +75 -0
- package/dist/esm/identity/index.d.ts +4 -0
- package/dist/esm/identity/index.js +4 -0
- package/dist/esm/identity/noteKey.d.ts +33 -0
- package/dist/esm/identity/noteKey.js +91 -0
- package/dist/esm/identity/spending.d.ts +18 -0
- package/dist/esm/identity/spending.js +35 -0
- package/dist/esm/identity/viewKey.d.ts +38 -0
- package/dist/esm/identity/viewKey.js +96 -0
- package/dist/esm/idl/index.d.ts +18 -0
- package/dist/esm/idl/index.js +18 -0
- package/dist/esm/idl/privacy_pool.json +9907 -9907
- package/dist/esm/idl/privacy_pool_legacy.d.ts +5 -0
- package/dist/esm/idl/privacy_pool_legacy.js +3305 -0
- package/dist/esm/idl/privacy_pool_legacy.json +2302 -0
- package/dist/esm/idl/privacy_pool_legacy2.d.ts +5 -0
- package/dist/esm/idl/privacy_pool_legacy2.js +3395 -0
- package/dist/esm/idl/privacy_pool_legacy2.json +2376 -0
- package/dist/esm/index.d.ts +8 -3
- package/dist/esm/index.js +8 -3
- package/dist/esm/notes/amount.d.ts +2 -0
- package/dist/esm/notes/amount.js +18 -0
- package/dist/esm/notes/index.d.ts +3 -0
- package/dist/esm/notes/index.js +3 -0
- package/dist/esm/notes/recovery.d.ts +16 -6
- package/dist/esm/notes/recovery.js +33 -16
- package/dist/esm/notes/selection.d.ts +77 -0
- package/dist/esm/notes/selection.js +188 -0
- package/dist/esm/notes/spent.d.ts +60 -0
- package/dist/esm/notes/spent.js +96 -0
- package/dist/esm/perps/constants.d.ts +16 -0
- package/dist/esm/perps/constants.js +48 -0
- package/dist/esm/perps/index.d.ts +5 -0
- package/dist/esm/perps/index.js +5 -0
- package/dist/esm/perps/keys.d.ts +16 -0
- package/dist/esm/perps/keys.js +35 -0
- package/dist/esm/perps/pdas.d.ts +29 -0
- package/dist/esm/perps/pdas.js +47 -0
- package/dist/esm/perps/relayer.d.ts +9 -0
- package/dist/esm/perps/relayer.js +25 -0
- package/dist/esm/perps/types.d.ts +126 -0
- package/dist/esm/perps/types.js +1 -0
- package/dist/esm/positions/index.d.ts +4 -0
- package/dist/esm/positions/index.js +4 -0
- package/dist/esm/positions/keys.d.ts +29 -0
- package/dist/esm/positions/keys.js +65 -0
- package/dist/esm/positions/pdas.d.ts +15 -0
- package/dist/esm/positions/pdas.js +44 -0
- package/dist/esm/positions/relayer.d.ts +4 -0
- package/dist/esm/positions/relayer.js +10 -0
- package/dist/esm/positions/types.d.ts +97 -0
- package/dist/esm/positions/types.js +1 -0
- package/dist/esm/predictions/client.d.ts +41 -0
- package/dist/esm/predictions/client.js +141 -0
- package/dist/esm/predictions/index.d.ts +5 -0
- package/dist/esm/predictions/index.js +5 -0
- package/dist/esm/predictions/keys.d.ts +14 -0
- package/dist/esm/predictions/keys.js +33 -0
- package/dist/esm/predictions/pdas.d.ts +6 -0
- package/dist/esm/predictions/pdas.js +10 -0
- package/dist/esm/predictions/relayer.d.ts +3 -0
- package/dist/esm/predictions/relayer.js +7 -0
- package/dist/esm/predictions/types.d.ts +178 -0
- package/dist/esm/predictions/types.js +1 -0
- package/dist/esm/program.d.ts +2 -0
- package/dist/esm/program.js +4 -3
- package/dist/esm/prover.d.ts +27 -4
- package/dist/esm/prover.js +106 -15
- package/dist/esm/relayer/api.d.ts +31 -0
- package/dist/esm/relayer/api.js +55 -0
- package/dist/esm/relayer/client.d.ts +29 -17
- package/dist/esm/relayer/client.js +72 -17
- package/dist/esm/relayer/errors.d.ts +1 -1
- package/dist/esm/relayer/errors.js +1 -1
- package/dist/esm/relayer/index.d.ts +4 -1
- package/dist/esm/relayer/index.js +1 -1
- package/dist/esm/relayer/internal-config.d.ts +36 -0
- package/dist/esm/relayer/internal-config.js +6 -0
- package/dist/esm/relayer/internal.d.ts +6 -0
- package/dist/esm/relayer/internal.js +10 -0
- package/dist/esm/relayer/transport.d.ts +4 -2
- package/dist/esm/relayer/transport.js +10 -5
- package/dist/esm/relayer/types.d.ts +9 -10
- package/dist/esm/relayer/types.js +1 -1
- package/dist/esm/shield/owner.js +1 -4
- package/identity.d.ts +2 -0
- package/identity.js +3 -0
- package/idl.d.ts +2 -0
- package/idl.js +3 -0
- package/notes.d.ts +2 -0
- package/notes.js +3 -0
- package/package.json +85 -3
- package/perps.d.ts +2 -0
- package/perps.js +3 -0
- package/poseidon.d.ts +2 -0
- package/poseidon.js +3 -0
- package/positions.d.ts +2 -0
- package/positions.js +3 -0
- package/predictions.d.ts +2 -0
- package/predictions.js +3 -0
- package/proof.d.ts +2 -0
- package/proof.js +3 -0
- package/prover.d.ts +2 -0
- package/prover.js +3 -0
- package/relayer.d.ts +2 -0
- package/relayer.js +3 -0
- package/shield.d.ts +2 -0
- package/shield.js +3 -0
- package/transactions.d.ts +2 -0
- package/transactions.js +3 -0
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@ The SDK gives TypeScript applications a safe, typed way to:
|
|
|
6
6
|
|
|
7
7
|
- shield SOL or SPL tokens into Veilo;
|
|
8
8
|
- withdraw, privately transfer, or privately swap shielded funds;
|
|
9
|
+
- open and manage private positions, Jupiter perps, and predictions;
|
|
9
10
|
- work with Veilo's relayer without handling its encryption protocol yourself;
|
|
10
11
|
- add partner-powered private sends and swaps through the Cloak API.
|
|
11
12
|
|
|
@@ -31,7 +32,7 @@ You will also need:
|
|
|
31
32
|
- a Solana RPC connection;
|
|
32
33
|
- a connected wallet when a user must sign;
|
|
33
34
|
- the Veilo circuit `.wasm` and `.zkey` files for local proof generation;
|
|
34
|
-
-
|
|
35
|
+
- an API key only for partner services such as Cloak or Jupiter Predictions.
|
|
35
36
|
|
|
36
37
|
## Choose an integration
|
|
37
38
|
|
|
@@ -39,7 +40,7 @@ You will also need:
|
|
|
39
40
|
| --- | --- | --- |
|
|
40
41
|
| Let any wallet shield funds into Veilo | `shield()` | The user's wallet |
|
|
41
42
|
| Add private transfers or swaps to a partner app | `VeiloCloakClient` | The user's wallet |
|
|
42
|
-
| Build a full Veilo wallet experience |
|
|
43
|
+
| Build a full Veilo wallet experience | Managed relayer helpers | The relayer for private spends |
|
|
43
44
|
| Manage proofs, notes, trees, and transactions yourself | Transaction helpers | Your application or relayer |
|
|
44
45
|
|
|
45
46
|
For most third-party deposit integrations, `shield()` is the best starting
|
|
@@ -231,31 +232,194 @@ that fits your application:
|
|
|
231
232
|
| Private transfer | `submitPrivateTransfer()` | `privateTransfer()` |
|
|
232
233
|
| Private swap | `submitPrivateSwap()` | `buildPrivateSwapInstructions()` or `transactSwap()` |
|
|
233
234
|
|
|
234
|
-
### Use the relayer
|
|
235
|
+
### Use the managed relayer helpers
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
The SDK owns Veilo's production relayer URL, encryption key, request encryption,
|
|
238
|
+
and safe retry behavior. Applications call typed functions directly; there is
|
|
239
|
+
no relayer client or URL to configure.
|
|
239
240
|
|
|
240
241
|
```ts
|
|
241
242
|
import {
|
|
242
|
-
|
|
243
|
+
submitWithdraw,
|
|
243
244
|
type WithdrawRequest,
|
|
244
245
|
} from "@veilo/sdk-core/relayer";
|
|
245
246
|
|
|
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,
|
|
250
|
-
});
|
|
251
|
-
|
|
252
247
|
async function submitWithdrawal(request: WithdrawRequest) {
|
|
253
|
-
return
|
|
248
|
+
return submitWithdraw(request);
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The same focused entry point provides account authentication, encrypted note
|
|
253
|
+
storage, Merkle tree reads, private transfers, private swaps, and these product
|
|
254
|
+
flows:
|
|
255
|
+
|
|
256
|
+
| Product | Relayer helpers |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| Private positions | `submitOpenPosition()`, `submitClosePosition()`, `submitMergePositions()` |
|
|
259
|
+
| Jupiter perps | `submitJperpOpen()`, `submitJperpClose()`, TP/SL, cancellation, recovery, and reissue helpers |
|
|
260
|
+
| Jupiter predictions | `submitPredictionOpen()` and `submitPredictionReissue()` |
|
|
261
|
+
|
|
262
|
+
#### Submission always targets Veilo's relayer
|
|
263
|
+
|
|
264
|
+
Every helper above submits to Veilo's relayer. There is no `baseUrl` option, no
|
|
265
|
+
client to construct, and no supported way to redirect submission. That is
|
|
266
|
+
deliberate, for two independent reasons:
|
|
267
|
+
|
|
268
|
+
1. **The program requires it.** The privacy pool checks the submitting relayer
|
|
269
|
+
against an on-chain allowlist on every spend. Deposits (`public_amount > 0`)
|
|
270
|
+
are permissionless — which is why `shield()` and `deposit()` work with any
|
|
271
|
+
wallet — but withdrawals, transfers, swaps, positions, perps, and predictions
|
|
272
|
+
all fail with `RelayerNotAllowed` unless the transaction is signed by a
|
|
273
|
+
whitelisted relayer. Pointing the SDK at a different host would produce a
|
|
274
|
+
well-formed request that cannot land on chain.
|
|
275
|
+
2. **These requests carry spending keys.** `TransactNote.privateKey`, and the
|
|
276
|
+
`claimantSecretKey` on position close and merge, *are* the spend authority for
|
|
277
|
+
the funds involved (see [A private note is valuable secret
|
|
278
|
+
data](#a-private-note-is-valuable-secret-data)). A configurable submission
|
|
279
|
+
target would be a configurable destination for user funds.
|
|
280
|
+
|
|
281
|
+
Running your own relayer is a whitelisting conversation rather than a
|
|
282
|
+
configuration flag — see [Support](#support). Reaching past the package's
|
|
283
|
+
`exports` map to import internal modules is unsupported and not covered by
|
|
284
|
+
semver.
|
|
285
|
+
|
|
286
|
+
### Spend status and private balance
|
|
287
|
+
|
|
288
|
+
Nothing in a note says whether it has been spent — a note is yours until its
|
|
289
|
+
nullifier is published. So a balance is always two steps, and the SDK gives you
|
|
290
|
+
both:
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
import { getPrivateBalance, checkNullifiersSpent } from "@veilo/sdk-core";
|
|
294
|
+
|
|
295
|
+
const { total, byMint, unspent, spent } = await getPrivateBalance(myNotes);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Each note needs an `amount`, a 64-character hex `nullifier`, and optionally a
|
|
299
|
+
`mint` to group by. `getPrivateBalance` asks the relayer which nullifiers are
|
|
300
|
+
spent, then sums what is left; `unspent` and `spent` hand back your own note
|
|
301
|
+
objects, so you can render from them directly.
|
|
302
|
+
|
|
303
|
+
`checkNullifiersSpent(nullifiers)` is the same question on its own. It
|
|
304
|
+
deduplicates, splits into the server's 200-per-request batches, issues them
|
|
305
|
+
concurrently, and returns a `Set` for membership testing. It also lower-cases
|
|
306
|
+
input: the endpoint validates case-insensitively but answers in lower case, so
|
|
307
|
+
upper-case hex would otherwise never match and every note would read as unspent.
|
|
308
|
+
|
|
309
|
+
To compute a balance without the relayer — from a chain scan of nullifier
|
|
310
|
+
events, or a local cache — supply the answer yourself:
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
await getPrivateBalance(myNotes, { resolveSpent: async (ns) => mySpentSet(ns) });
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Amounts stay `bigint` end to end. A `number` amount above `Number.MAX_SAFE_INTEGER`
|
|
317
|
+
is rejected rather than silently rounded, and a malformed nullifier throws
|
|
318
|
+
instead of counting as unspent — either would overstate a balance.
|
|
319
|
+
|
|
320
|
+
### Choosing notes to spend
|
|
321
|
+
|
|
322
|
+
Two rules govern this, and both are easy to get wrong:
|
|
323
|
+
|
|
324
|
+
- the transaction circuit is **2-in-2-out**, so one transaction spends at most
|
|
325
|
+
two notes;
|
|
326
|
+
- notes are only co-spendable inside the **same Merkle tree**, and the tree is
|
|
327
|
+
derived from the mint.
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
import { selectNotesForAmount, canonicalTreeId } from "@veilo/sdk-core";
|
|
331
|
+
|
|
332
|
+
const selection = selectNotesForAmount(unspentNotes, amountRaw, { mint });
|
|
333
|
+
if (!selection.ok) throw new Error(selection.message); // NO_NOTES | INSUFFICIENT_FUNDS
|
|
334
|
+
if (selection.requiresMerge) {
|
|
335
|
+
// more than two inputs — combine them before proving
|
|
254
336
|
}
|
|
255
337
|
```
|
|
256
338
|
|
|
257
|
-
|
|
258
|
-
|
|
339
|
+
It searches each tree independently and returns the best result: the smallest
|
|
340
|
+
single note that covers the amount, else the pair with the least change (found
|
|
341
|
+
by a two-pointer scan, not an all-pairs search), else the largest notes greedily
|
|
342
|
+
with `requiresMerge` set. A failure reports `available`, the largest total
|
|
343
|
+
reachable within one tree.
|
|
344
|
+
|
|
345
|
+
`canonicalTreeId(mint)` derives a note's tree the way the relayer does. **Derive
|
|
346
|
+
it; never trust a stored `treeId`.** Change notes are written with the on-chain
|
|
347
|
+
shard index while deposits and synced notes carry the mint-derived id — for
|
|
348
|
+
native SOL both are 0 so the difference hides, but for SPL tokens they diverge
|
|
349
|
+
and co-spending across the two fails at proof time as a commitment mismatch.
|
|
350
|
+
|
|
351
|
+
### Private product keys and recovery
|
|
352
|
+
|
|
353
|
+
Private positions, perps, and predictions use deterministic client-held keys.
|
|
354
|
+
The SDK provides the exact derivations used by Veilo's wallet, extension,
|
|
355
|
+
relayer, and program tests. Keep the spending key and claimant secret on the
|
|
356
|
+
user's device; send claimant secrets only inside the SDK's encrypted relayer
|
|
357
|
+
requests.
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
import {
|
|
361
|
+
derivePositionKeyBundle,
|
|
362
|
+
deriveSpendingKeyWithSigner,
|
|
363
|
+
encodeClaimantSecretKey,
|
|
364
|
+
initPoseidon,
|
|
365
|
+
submitOpenPosition,
|
|
366
|
+
} from "@veilo/sdk-core";
|
|
367
|
+
|
|
368
|
+
await initPoseidon();
|
|
369
|
+
const spendingKey = await deriveSpendingKeyWithSigner(
|
|
370
|
+
(message) => wallet.signMessage(message),
|
|
371
|
+
);
|
|
372
|
+
const positionKeys = derivePositionKeyBundle(spendingKey, nextPositionIndex);
|
|
373
|
+
|
|
374
|
+
await submitOpenPosition({
|
|
375
|
+
// Select private source notes in your wallet before calling the relayer.
|
|
376
|
+
notes,
|
|
377
|
+
sourceMintAddress,
|
|
378
|
+
destMintAddress,
|
|
379
|
+
swapAmountRaw,
|
|
380
|
+
slippageBps: 50,
|
|
381
|
+
userPublicKey: wallet.publicKey.toBase58(),
|
|
382
|
+
veiloPublicKey,
|
|
383
|
+
position: positionKeys.position,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Persist the returned position data and `nextPositionIndex`. Re-derive the
|
|
387
|
+
// same claimant later when closing or merging the position.
|
|
388
|
+
const claimantSecretKey = encodeClaimantSecretKey(positionKeys.claimant);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Use `deriveJperpKeyBundle()` and `getJperpMarketPayload()` for private perps.
|
|
392
|
+
Use `derivePredictionKeyBundle()` for private predictions. Lower-level key
|
|
393
|
+
derivations are also exported when an application needs them individually. The
|
|
394
|
+
PDA helpers in each focused entry point support on-chain recovery scans on a
|
|
395
|
+
fresh device.
|
|
396
|
+
|
|
397
|
+
Predictions have one additional step: Jupiter returns an unsigned order,
|
|
398
|
+
close, or claim transaction. The SDK exposes that API without taking custody
|
|
399
|
+
of signing:
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
import {
|
|
403
|
+
JupiterPredictionClient,
|
|
404
|
+
deserializePredictionTransaction,
|
|
405
|
+
} from "@veilo/sdk-core/predictions";
|
|
406
|
+
|
|
407
|
+
const predictions = new JupiterPredictionClient({ apiKey: jupiterApiKey });
|
|
408
|
+
const order = await predictions.placeOrder({
|
|
409
|
+
ownerPubkey: ephemeral.publicKey.toBase58(),
|
|
410
|
+
marketId,
|
|
411
|
+
isYes: true,
|
|
412
|
+
isBuy: true,
|
|
413
|
+
depositAmount: "5000000",
|
|
414
|
+
depositMint: usdcMint,
|
|
415
|
+
});
|
|
416
|
+
const transaction = deserializePredictionTransaction(order);
|
|
417
|
+
// Ask the deterministic ephemeral wallet to sign, then submit and confirm it.
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
The SDK deliberately does not own application storage or choose which notes to
|
|
421
|
+
spend. Persist indexes and returned product records only after the corresponding
|
|
422
|
+
transaction is confirmed.
|
|
259
423
|
|
|
260
424
|
### Use the direct helpers
|
|
261
425
|
|
|
@@ -347,8 +511,28 @@ for shields and call a deposit's `commit()` callback only after confirmation.
|
|
|
347
511
|
### Proof files are separate
|
|
348
512
|
|
|
349
513
|
Circuit `.wasm` and `.zkey` files are intentionally not bundled with the npm
|
|
350
|
-
package because they are large
|
|
351
|
-
to `createTransactionProver()` and
|
|
514
|
+
package because they are large — `files` ships `dist/` only. Provide local
|
|
515
|
+
paths, byte arrays, or hosted URLs to `createTransactionProver()` and
|
|
516
|
+
`createSwapProver()`.
|
|
517
|
+
|
|
518
|
+
Both arguments are optional. Omit them and the prover resolves artifacts from
|
|
519
|
+
disk on first use, first hit wins:
|
|
520
|
+
|
|
521
|
+
1. `$VEILO_CIRCUITS_DIR`
|
|
522
|
+
2. `<package>/circuits` — populated by `npm run copy:circuits`
|
|
523
|
+
3. `<cwd>/circuits`
|
|
524
|
+
4. `<cwd>/node_modules/@veilo/sdk-core/circuits`
|
|
525
|
+
|
|
526
|
+
```ts
|
|
527
|
+
const prover = createTransactionProver(); // resolved from disk
|
|
528
|
+
const prover = createTransactionProver({ wasmPath, zkeyPath }); // explicit
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
`resolveCircuitArtifacts("transaction" | "swap")` performs that lookup on its
|
|
532
|
+
own if you want the paths. Resolution is **Node-only and lazy** — it imports
|
|
533
|
+
`node:fs` inside the call so browser bundles can still import this module, and
|
|
534
|
+
there is nothing to resolve in a browser anyway. Browser builds must pass
|
|
535
|
+
`CircuitArtifacts` explicitly. A miss throws with every path it tried.
|
|
352
536
|
|
|
353
537
|
## Error handling
|
|
354
538
|
|
|
@@ -388,8 +572,11 @@ import { shield } from "@veilo/sdk-core";
|
|
|
388
572
|
import { getPoolPdas } from "@veilo/sdk-core/accounts";
|
|
389
573
|
import { createUTXO } from "@veilo/sdk-core/notes";
|
|
390
574
|
import { deposit, withdraw } from "@veilo/sdk-core/transactions";
|
|
391
|
-
import {
|
|
575
|
+
import { submitWithdraw } from "@veilo/sdk-core/relayer";
|
|
392
576
|
import { VeiloCloakClient } from "@veilo/sdk-core/cloak";
|
|
577
|
+
import { derivePositionKeyBundle } from "@veilo/sdk-core/positions";
|
|
578
|
+
import { getJperpMarketPayload } from "@veilo/sdk-core/perps";
|
|
579
|
+
import { JupiterPredictionClient } from "@veilo/sdk-core/predictions";
|
|
393
580
|
```
|
|
394
581
|
|
|
395
582
|
Available focused entry points:
|
|
@@ -397,7 +584,12 @@ Available focused entry points:
|
|
|
397
584
|
- `@veilo/sdk-core/accounts`
|
|
398
585
|
- `@veilo/sdk-core/cloak`
|
|
399
586
|
- `@veilo/sdk-core/config`
|
|
587
|
+
- `@veilo/sdk-core/idl`
|
|
588
|
+
- `@veilo/sdk-core/identity`
|
|
400
589
|
- `@veilo/sdk-core/notes`
|
|
590
|
+
- `@veilo/sdk-core/perps`
|
|
591
|
+
- `@veilo/sdk-core/positions`
|
|
592
|
+
- `@veilo/sdk-core/predictions`
|
|
401
593
|
- `@veilo/sdk-core/poseidon`
|
|
402
594
|
- `@veilo/sdk-core/proof`
|
|
403
595
|
- `@veilo/sdk-core/prover`
|
|
@@ -421,6 +613,32 @@ or relayer:
|
|
|
421
613
|
These APIs are fully typed. Use their TypeScript definitions as the source of
|
|
422
614
|
truth for required inputs.
|
|
423
615
|
|
|
616
|
+
### Historical IDLs and commitment recovery
|
|
617
|
+
|
|
618
|
+
The SDK includes the current, legacy, and legacy-2 privacy-pool IDLs used by the
|
|
619
|
+
relayer. Event scans automatically try the historical layouts, so applications
|
|
620
|
+
can rebuild trees across program upgrades.
|
|
621
|
+
|
|
622
|
+
```ts
|
|
623
|
+
import {
|
|
624
|
+
PRIVACY_POOL_IDLS,
|
|
625
|
+
buildTreeFromEvents,
|
|
626
|
+
resolveCommitmentEvents,
|
|
627
|
+
} from "@veilo/sdk-core";
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
`buildTreeFromEvents()` includes Veilo's protected historical repairs by
|
|
631
|
+
default and rejects gaps that would produce an incorrect root. When a confirmed
|
|
632
|
+
instruction appended commitments without emitting `CommitmentEvent`, use
|
|
633
|
+
`resolveCommitmentEvents()` with the expected commitments and current local
|
|
634
|
+
tree. It prefers emitted metadata and computes only the missing entries.
|
|
635
|
+
|
|
636
|
+
For the deployed eventless `open_position` path, use
|
|
637
|
+
`recoverEventlessOpenPositionEvents()`. It decodes both commitments from the
|
|
638
|
+
instruction and reads the authoritative global position-tree leaf index from
|
|
639
|
+
the program-owned PositionPDA. `buildGlobalPositionTreeFromEvents()` mirrors
|
|
640
|
+
the relayer's all-mint position-tree reconstruction.
|
|
641
|
+
|
|
424
642
|
## Development
|
|
425
643
|
|
|
426
644
|
```bash
|
package/accounts.d.ts
ADDED
package/accounts.js
ADDED
package/cloak.d.ts
ADDED
package/cloak.js
ADDED
package/config.d.ts
ADDED
package/config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types.js"), exports);
|
|
18
|
+
__exportStar(require("./parsing.js"), exports);
|
|
19
|
+
__exportStar(require("./position.js"), exports);
|
|
20
|
+
__exportStar(require("./recovery.js"), exports);
|
|
21
|
+
__exportStar(require("./scanning.js"), exports);
|
|
22
|
+
__exportStar(require("./tree.js"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { type VersionedPrivacyPoolIdl } from "../idl/index.js";
|
|
3
|
+
import type { CommitmentEvent, NullifierSpentEvent, ParsedVeiloEvent } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Decode logs using the current, legacy, and legacy-2 IDLs.
|
|
6
|
+
*
|
|
7
|
+
* IDLs are evaluated in the relayer's current/legacy/legacy-2 order. Anchor's
|
|
8
|
+
* Borsh decoder accepts trailing bytes, however, so every successful parse is
|
|
9
|
+
* considered and the richest result wins. That preserves the compact fields
|
|
10
|
+
* in legacy-2 events instead of misclassifying them as the shorter legacy form.
|
|
11
|
+
* Ties retain the relayer's order.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseVeiloEventsWithFallback(logMessages: readonly string[] | null | undefined, programId: PublicKey, idls?: readonly VersionedPrivacyPoolIdl[]): ParsedVeiloEvent[];
|
|
14
|
+
export declare function parseCommitmentEventsFromLogs(params: {
|
|
15
|
+
logMessages: readonly string[] | null | undefined;
|
|
16
|
+
programId: PublicKey;
|
|
17
|
+
txSignature: string;
|
|
18
|
+
slot: number;
|
|
19
|
+
}): CommitmentEvent[];
|
|
20
|
+
export declare function parseNullifierEventsFromLogs(params: {
|
|
21
|
+
logMessages: readonly string[] | null | undefined;
|
|
22
|
+
programId: PublicKey;
|
|
23
|
+
txSignature: string;
|
|
24
|
+
slot: number;
|
|
25
|
+
}): NullifierSpentEvent[];
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseVeiloEventsWithFallback = parseVeiloEventsWithFallback;
|
|
37
|
+
exports.parseCommitmentEventsFromLogs = parseCommitmentEventsFromLogs;
|
|
38
|
+
exports.parseNullifierEventsFromLogs = parseNullifierEventsFromLogs;
|
|
39
|
+
const anchor = __importStar(require("@coral-xyz/anchor"));
|
|
40
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
41
|
+
const index_js_1 = require("../idl/index.js");
|
|
42
|
+
/**
|
|
43
|
+
* Decode logs using the current, legacy, and legacy-2 IDLs.
|
|
44
|
+
*
|
|
45
|
+
* IDLs are evaluated in the relayer's current/legacy/legacy-2 order. Anchor's
|
|
46
|
+
* Borsh decoder accepts trailing bytes, however, so every successful parse is
|
|
47
|
+
* considered and the richest result wins. That preserves the compact fields
|
|
48
|
+
* in legacy-2 events instead of misclassifying them as the shorter legacy form.
|
|
49
|
+
* Ties retain the relayer's order.
|
|
50
|
+
*/
|
|
51
|
+
function parseVeiloEventsWithFallback(logMessages, programId, idls = index_js_1.PRIVACY_POOL_IDLS) {
|
|
52
|
+
if (!logMessages?.length)
|
|
53
|
+
return [];
|
|
54
|
+
let best = [];
|
|
55
|
+
let bestScore = -1;
|
|
56
|
+
for (const candidate of idls) {
|
|
57
|
+
try {
|
|
58
|
+
const parser = new anchor.EventParser(programId, new anchor.BorshCoder(candidate.idl));
|
|
59
|
+
const parsed = Array.from(parser.parseLogs([...logMessages])).map((event) => ({
|
|
60
|
+
name: event.name,
|
|
61
|
+
data: event.data,
|
|
62
|
+
idlVersion: candidate.version,
|
|
63
|
+
}));
|
|
64
|
+
const score = parsed.reduce((total, event) => total + decodedFieldCount(event.data), 0);
|
|
65
|
+
if (score > bestScore) {
|
|
66
|
+
best = parsed;
|
|
67
|
+
bestScore = score;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// The discriminator is shared while historical payload lengths differ.
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return best;
|
|
75
|
+
}
|
|
76
|
+
function parseCommitmentEventsFromLogs(params) {
|
|
77
|
+
const { logMessages, programId, txSignature, slot } = params;
|
|
78
|
+
const out = [];
|
|
79
|
+
for (const event of parseVeiloEventsWithFallback(logMessages, programId)) {
|
|
80
|
+
if (event.name.toLowerCase() !== "commitmentevent")
|
|
81
|
+
continue;
|
|
82
|
+
const data = event.data;
|
|
83
|
+
const mintAddress = toPublicKey(field(data, "mintAddress", "mint_address"));
|
|
84
|
+
const ephemeralPublicKey = optionalBytes(field(data, "ephemeralPublicKey", "ephemeral_public_key"));
|
|
85
|
+
const encryptedBlob = optionalBytes(field(data, "encryptedBlob", "encrypted_blob"));
|
|
86
|
+
const rawViewTag = field(data, "viewTag", "view_tag");
|
|
87
|
+
out.push({
|
|
88
|
+
commitment: toBytes(field(data, "commitment"), 32, "commitment"),
|
|
89
|
+
leafIndex: toSafeNumber(field(data, "leafIndex", "leaf_index"), "leafIndex"),
|
|
90
|
+
newRoot: toBytes(field(data, "newRoot", "new_root"), 32, "newRoot"),
|
|
91
|
+
timestamp: toSafeNumber(field(data, "timestamp"), "timestamp"),
|
|
92
|
+
mintAddress,
|
|
93
|
+
treeId: toSafeNumber(field(data, "treeId", "tree_id"), "treeId"),
|
|
94
|
+
txSignature,
|
|
95
|
+
slot,
|
|
96
|
+
...(ephemeralPublicKey ? { ephemeralPublicKey } : {}),
|
|
97
|
+
...(encryptedBlob ? { encryptedBlob } : {}),
|
|
98
|
+
...(rawViewTag !== undefined
|
|
99
|
+
? { viewTag: toSafeNumber(rawViewTag, "viewTag") }
|
|
100
|
+
: {}),
|
|
101
|
+
source: "emitted",
|
|
102
|
+
idlVersion: event.idlVersion,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
function parseNullifierEventsFromLogs(params) {
|
|
108
|
+
const { logMessages, programId, txSignature, slot } = params;
|
|
109
|
+
const out = [];
|
|
110
|
+
for (const event of parseVeiloEventsWithFallback(logMessages, programId)) {
|
|
111
|
+
if (event.name.toLowerCase() !== "nullifierspent")
|
|
112
|
+
continue;
|
|
113
|
+
const data = event.data;
|
|
114
|
+
out.push({
|
|
115
|
+
nullifier: toBytes(field(data, "nullifier"), 32, "nullifier"),
|
|
116
|
+
timestamp: toSafeNumber(field(data, "timestamp"), "timestamp"),
|
|
117
|
+
mintAddress: toPublicKey(field(data, "mintAddress", "mint_address")),
|
|
118
|
+
treeId: toSafeNumber(field(data, "treeId", "tree_id"), "treeId"),
|
|
119
|
+
txSignature,
|
|
120
|
+
slot,
|
|
121
|
+
idlVersion: event.idlVersion,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
function field(data, camel, snake) {
|
|
127
|
+
return data[camel] ?? (snake ? data[snake] : undefined);
|
|
128
|
+
}
|
|
129
|
+
function optionalBytes(value) {
|
|
130
|
+
return value === undefined || value === null
|
|
131
|
+
? undefined
|
|
132
|
+
: new Uint8Array(value);
|
|
133
|
+
}
|
|
134
|
+
function decodedFieldCount(value) {
|
|
135
|
+
return value && typeof value === "object" ? Object.keys(value).length : 0;
|
|
136
|
+
}
|
|
137
|
+
function toBytes(value, length, label) {
|
|
138
|
+
const bytes = new Uint8Array(value);
|
|
139
|
+
if (bytes.length !== length) {
|
|
140
|
+
throw new Error(`${label} must be ${length} bytes, got ${bytes.length}`);
|
|
141
|
+
}
|
|
142
|
+
return bytes;
|
|
143
|
+
}
|
|
144
|
+
function toPublicKey(value) {
|
|
145
|
+
if (value instanceof web3_js_1.PublicKey)
|
|
146
|
+
return value;
|
|
147
|
+
return new web3_js_1.PublicKey(value);
|
|
148
|
+
}
|
|
149
|
+
function toSafeNumber(value, label) {
|
|
150
|
+
if (value === undefined || value === null) {
|
|
151
|
+
throw new Error(`Missing ${label} in decoded event`);
|
|
152
|
+
}
|
|
153
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
154
|
+
if (!Number.isSafeInteger(numeric)) {
|
|
155
|
+
throw new Error(`${label} is outside JavaScript's safe integer range`);
|
|
156
|
+
}
|
|
157
|
+
return numeric;
|
|
158
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Idl, Program } from "@coral-xyz/anchor";
|
|
2
|
+
import { PublicKey } from "@solana/web3.js";
|
|
3
|
+
import type { CommitmentEvent } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Privacy-pool mints copied from the relayer's global position-tree classifier.
|
|
6
|
+
* Position commitments use non-pool destination mints at the same tree ID.
|
|
7
|
+
*/
|
|
8
|
+
export declare const POSITION_TREE_POOL_MINTS: readonly PublicKey[];
|
|
9
|
+
export declare function isGlobalPositionCommitment(event: CommitmentEvent): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Rebuild the one global position tree shared across every position mint.
|
|
12
|
+
* This mirrors the relayer: scan all mints for the position tree ID, then drop
|
|
13
|
+
* normal privacy-pool mint events before sorting by the global leaf index.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildGlobalPositionTreeFromEvents<T extends Idl>(params: {
|
|
16
|
+
program: Program<T>;
|
|
17
|
+
positionTreeId?: number;
|
|
18
|
+
depth?: number;
|
|
19
|
+
additionalEvents?: readonly CommitmentEvent[];
|
|
20
|
+
includeProtectedEvents?: boolean;
|
|
21
|
+
strictLeafIndices?: boolean;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
tree: import("../merkle.js").MerkleTree;
|
|
24
|
+
events: CommitmentEvent[];
|
|
25
|
+
latestSignature: string;
|
|
26
|
+
}>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POSITION_TREE_POOL_MINTS = void 0;
|
|
4
|
+
exports.isGlobalPositionCommitment = isGlobalPositionCommitment;
|
|
5
|
+
exports.buildGlobalPositionTreeFromEvents = buildGlobalPositionTreeFromEvents;
|
|
6
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
7
|
+
const recovery_js_1 = require("./recovery.js");
|
|
8
|
+
const scanning_js_1 = require("./scanning.js");
|
|
9
|
+
const tree_js_1 = require("./tree.js");
|
|
10
|
+
/**
|
|
11
|
+
* Privacy-pool mints copied from the relayer's global position-tree classifier.
|
|
12
|
+
* Position commitments use non-pool destination mints at the same tree ID.
|
|
13
|
+
*/
|
|
14
|
+
exports.POSITION_TREE_POOL_MINTS = [
|
|
15
|
+
web3_js_1.PublicKey.default,
|
|
16
|
+
new web3_js_1.PublicKey("So11111111111111111111111111111111111111112"),
|
|
17
|
+
new web3_js_1.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
|
|
18
|
+
new web3_js_1.PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"),
|
|
19
|
+
new web3_js_1.PublicKey("USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB"),
|
|
20
|
+
new web3_js_1.PublicKey("JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"),
|
|
21
|
+
new web3_js_1.PublicKey("ARXwZkNAtzPfdcoqQiduJn8EPv9fKiDfGn2KyggyDrFs"),
|
|
22
|
+
];
|
|
23
|
+
const POOL_MINTS = new Set(exports.POSITION_TREE_POOL_MINTS.map((mint) => mint.toBase58()));
|
|
24
|
+
function isGlobalPositionCommitment(event) {
|
|
25
|
+
return !POOL_MINTS.has(event.mintAddress.toBase58());
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Rebuild the one global position tree shared across every position mint.
|
|
29
|
+
* This mirrors the relayer: scan all mints for the position tree ID, then drop
|
|
30
|
+
* normal privacy-pool mint events before sorting by the global leaf index.
|
|
31
|
+
*/
|
|
32
|
+
async function buildGlobalPositionTreeFromEvents(params) {
|
|
33
|
+
const { program, positionTreeId = 0, depth = 22, additionalEvents = [], includeProtectedEvents = true, strictLeafIndices = true, } = params;
|
|
34
|
+
const emitted = await (0, scanning_js_1.scanAllCommitmentEvents)({ program });
|
|
35
|
+
const protectedEvents = includeProtectedEvents
|
|
36
|
+
? (0, recovery_js_1.getAllProtectedCommitmentEvents)()
|
|
37
|
+
: [];
|
|
38
|
+
const events = (0, tree_js_1.dedupeCommitmentEvents)([
|
|
39
|
+
...emitted,
|
|
40
|
+
...additionalEvents,
|
|
41
|
+
...protectedEvents,
|
|
42
|
+
])
|
|
43
|
+
.filter((event) => event.treeId === positionTreeId && isGlobalPositionCommitment(event))
|
|
44
|
+
.sort((a, b) => a.leafIndex - b.leafIndex);
|
|
45
|
+
return {
|
|
46
|
+
tree: (0, tree_js_1.reconstructTreeFromCommitmentEvents)(events, {
|
|
47
|
+
depth,
|
|
48
|
+
strictLeafIndices,
|
|
49
|
+
}),
|
|
50
|
+
events,
|
|
51
|
+
latestSignature: events[events.length - 1]?.txSignature,
|
|
52
|
+
};
|
|
53
|
+
}
|