@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
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("mocha");
|
|
4
|
-
const assert_1 = require("assert");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
const src_1 = require("../src");
|
|
7
|
-
describe("Config constants and fee helpers", function () {
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// Constants
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
describe("constants", () => {
|
|
12
|
-
it("DEFAULT_FEE_BPS is 50 (0.5%)", () => {
|
|
13
|
-
assert_1.strict.equal(src_1.DEFAULT_FEE_BPS, 50);
|
|
14
|
-
});
|
|
15
|
-
it("MERKLE_TREE_DEPTH is 22", () => {
|
|
16
|
-
assert_1.strict.equal(src_1.MERKLE_TREE_DEPTH, 22);
|
|
17
|
-
});
|
|
18
|
-
it("ROOT_HISTORY_SIZE is 256", () => {
|
|
19
|
-
assert_1.strict.equal(src_1.ROOT_HISTORY_SIZE, 256);
|
|
20
|
-
});
|
|
21
|
-
it("NATIVE_SOL_MINT is the all-zeros public key", () => {
|
|
22
|
-
assert_1.strict.equal(src_1.NATIVE_SOL_MINT.toBase58(), "11111111111111111111111111111111");
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
// sol()
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
|
-
describe("sol()", () => {
|
|
29
|
-
it("converts 1 SOL to 1_000_000_000 lamports", () => {
|
|
30
|
-
assert_1.strict.equal((0, src_1.sol)(1), BigInt(web3_js_1.LAMPORTS_PER_SOL));
|
|
31
|
-
});
|
|
32
|
-
it("converts 0 SOL to 0 lamports", () => {
|
|
33
|
-
assert_1.strict.equal((0, src_1.sol)(0), 0n);
|
|
34
|
-
});
|
|
35
|
-
it("converts 0.1 SOL correctly", () => {
|
|
36
|
-
assert_1.strict.equal((0, src_1.sol)(0.1), BigInt(0.1 * web3_js_1.LAMPORTS_PER_SOL));
|
|
37
|
-
});
|
|
38
|
-
it("returns a bigint", () => {
|
|
39
|
-
assert_1.strict.equal(typeof (0, src_1.sol)(1), "bigint");
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
// computeWithdrawalFee
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
describe("computeWithdrawalFee", () => {
|
|
46
|
-
it("uses percentage fee when it exceeds minimum", () => {
|
|
47
|
-
// 1_000_000 * 50 / 10_000 = 5000 > 0 (min)
|
|
48
|
-
const { fee, toRecipient } = (0, src_1.computeWithdrawalFee)(1000000n, 50, 0n);
|
|
49
|
-
assert_1.strict.equal(fee, 5000n);
|
|
50
|
-
assert_1.strict.equal(toRecipient, 995000n);
|
|
51
|
-
});
|
|
52
|
-
it("uses minimum fee when percentage is below it", () => {
|
|
53
|
-
// 100 * 50 / 10_000 = 0, min = 500 → fee = 500
|
|
54
|
-
const { fee, toRecipient } = (0, src_1.computeWithdrawalFee)(10000n, 50, 1000n);
|
|
55
|
-
// 10_000 * 50 / 10_000 = 50 < 1000 → fee = 1000
|
|
56
|
-
assert_1.strict.equal(fee, 1000n);
|
|
57
|
-
assert_1.strict.equal(toRecipient, 9000n);
|
|
58
|
-
});
|
|
59
|
-
it("toRecipient = amount - fee", () => {
|
|
60
|
-
const amount = 5000000n;
|
|
61
|
-
const { fee, toRecipient } = (0, src_1.computeWithdrawalFee)(amount, 100, 0n);
|
|
62
|
-
assert_1.strict.equal(fee + toRecipient, amount);
|
|
63
|
-
});
|
|
64
|
-
it("zero feeBps with zero minimum gives zero fee", () => {
|
|
65
|
-
const { fee, toRecipient } = (0, src_1.computeWithdrawalFee)(999n, 0, 0n);
|
|
66
|
-
assert_1.strict.equal(fee, 0n);
|
|
67
|
-
assert_1.strict.equal(toRecipient, 999n);
|
|
68
|
-
});
|
|
69
|
-
it("100% feeBps (10000) takes the entire amount", () => {
|
|
70
|
-
const { fee, toRecipient } = (0, src_1.computeWithdrawalFee)(1000n, 10000, 0n);
|
|
71
|
-
assert_1.strict.equal(fee, 1000n);
|
|
72
|
-
assert_1.strict.equal(toRecipient, 0n);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
// computeSwapFee
|
|
77
|
-
// ---------------------------------------------------------------------------
|
|
78
|
-
describe("computeSwapFee", () => {
|
|
79
|
-
it("uses percentage fee when it exceeds minimum", () => {
|
|
80
|
-
// 100_000 * 50 / 10_000 = 500 > 0 (min)
|
|
81
|
-
const { relayerFee, destAmount } = (0, src_1.computeSwapFee)(100000n, 50, 0n, 90000n);
|
|
82
|
-
assert_1.strict.equal(relayerFee, 500n);
|
|
83
|
-
assert_1.strict.equal(destAmount, 89500n);
|
|
84
|
-
});
|
|
85
|
-
it("uses minimum fee when percentage is below it", () => {
|
|
86
|
-
// 100_000 * 50 / 10_000 = 500 < 1000 → relayerFee = 1000
|
|
87
|
-
const { relayerFee, destAmount } = (0, src_1.computeSwapFee)(100000n, 50, 1000n, 90000n);
|
|
88
|
-
assert_1.strict.equal(relayerFee, 1000n);
|
|
89
|
-
assert_1.strict.equal(destAmount, 89000n);
|
|
90
|
-
});
|
|
91
|
-
it("destAmount = minAmountOut - relayerFee", () => {
|
|
92
|
-
const minAmountOut = 50000n;
|
|
93
|
-
const { relayerFee, destAmount } = (0, src_1.computeSwapFee)(200000n, 100, 0n, minAmountOut);
|
|
94
|
-
assert_1.strict.equal(relayerFee + destAmount, minAmountOut);
|
|
95
|
-
});
|
|
96
|
-
it("zero swapFeeBps with zero min fee gives zero relayer fee", () => {
|
|
97
|
-
const { relayerFee, destAmount } = (0, src_1.computeSwapFee)(100000n, 0, 0n, 80000n);
|
|
98
|
-
assert_1.strict.equal(relayerFee, 0n);
|
|
99
|
-
assert_1.strict.equal(destAmount, 80000n);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "mocha";
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("mocha");
|
|
4
|
-
const assert_1 = require("assert");
|
|
5
|
-
const src_1 = require("../src");
|
|
6
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
7
|
-
describe("Edge cases", function () {
|
|
8
|
-
this.timeout(15000);
|
|
9
|
-
before(async () => {
|
|
10
|
-
await (0, src_1.initPoseidon)();
|
|
11
|
-
});
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
// Zero amounts
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
describe("Zero-amount UTXOs", () => {
|
|
16
|
-
it("creates a UTXO with amount 0", () => {
|
|
17
|
-
const kp = (0, src_1.generateKeypair)();
|
|
18
|
-
const utxo = (0, src_1.createUTXO)({
|
|
19
|
-
amount: 0n,
|
|
20
|
-
pubkey: kp.publicKey,
|
|
21
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
22
|
-
});
|
|
23
|
-
assert_1.strict.equal(utxo.amount, 0n);
|
|
24
|
-
assert_1.strict.equal(utxo.commitment.length, 32);
|
|
25
|
-
});
|
|
26
|
-
it("zero-amount UTXOs produce unique commitments due to blinding", () => {
|
|
27
|
-
const kp = (0, src_1.generateKeypair)();
|
|
28
|
-
const utxo1 = (0, src_1.createUTXO)({ amount: 0n, pubkey: kp.publicKey, mintAddress: src_1.NATIVE_SOL_MINT });
|
|
29
|
-
const utxo2 = (0, src_1.createUTXO)({ amount: 0n, pubkey: kp.publicKey, mintAddress: src_1.NATIVE_SOL_MINT });
|
|
30
|
-
// Different blinding values should give different commitments
|
|
31
|
-
if (utxo1.blinding !== utxo2.blinding) {
|
|
32
|
-
assert_1.strict.notDeepEqual(utxo1.commitment, utxo2.commitment);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
it("owned zero UTXO has correct structure", () => {
|
|
36
|
-
const pk = 99999n;
|
|
37
|
-
const utxo = (0, src_1.createOwnedZeroUTXO)(pk, src_1.NATIVE_SOL_MINT);
|
|
38
|
-
assert_1.strict.equal(utxo.amount, 0n);
|
|
39
|
-
assert_1.strict.equal(utxo.privateKey, pk);
|
|
40
|
-
assert_1.strict.equal(utxo.commitment.length, 32);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
// Large / boundary amounts
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
describe("Boundary amounts", () => {
|
|
47
|
-
it("handles amount of 1 (smallest positive)", () => {
|
|
48
|
-
const kp = (0, src_1.generateKeypair)();
|
|
49
|
-
const utxo = (0, src_1.createUTXO)({ amount: 1n, pubkey: kp.publicKey, mintAddress: src_1.NATIVE_SOL_MINT });
|
|
50
|
-
assert_1.strict.equal(utxo.amount, 1n);
|
|
51
|
-
assert_1.strict.equal(utxo.commitment.length, 32);
|
|
52
|
-
});
|
|
53
|
-
it("handles large amount near u64 max", () => {
|
|
54
|
-
const kp = (0, src_1.generateKeypair)();
|
|
55
|
-
const amount = (1n << 64n) - 1n; // u64 max
|
|
56
|
-
const utxo = (0, src_1.createUTXO)({ amount, pubkey: kp.publicKey, mintAddress: src_1.NATIVE_SOL_MINT });
|
|
57
|
-
assert_1.strict.equal(utxo.amount, amount);
|
|
58
|
-
assert_1.strict.equal(utxo.commitment.length, 32);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
// ---------------------------------------------------------------------------
|
|
62
|
-
// Merkle tree edge cases
|
|
63
|
-
// ---------------------------------------------------------------------------
|
|
64
|
-
describe("Merkle tree", () => {
|
|
65
|
-
it("small depth=1 tree holds exactly 2 leaves", () => {
|
|
66
|
-
const tree = new src_1.MerkleTree(1);
|
|
67
|
-
const c1 = new Uint8Array(32).fill(0xaa);
|
|
68
|
-
const c2 = new Uint8Array(32).fill(0xbb);
|
|
69
|
-
tree.insert(c1);
|
|
70
|
-
tree.insert(c2);
|
|
71
|
-
// Tree should be full
|
|
72
|
-
assert_1.strict.equal(tree.getPath(0).path.length, 1);
|
|
73
|
-
assert_1.strict.equal(tree.getPath(1).path.length, 1);
|
|
74
|
-
});
|
|
75
|
-
it("tree root changes with each insert", () => {
|
|
76
|
-
const tree = new src_1.MerkleTree(4);
|
|
77
|
-
const roots = [];
|
|
78
|
-
for (let i = 0; i < 5; i++) {
|
|
79
|
-
const c = new Uint8Array(32);
|
|
80
|
-
c[0] = i;
|
|
81
|
-
tree.insert(c);
|
|
82
|
-
roots.push(Uint8Array.from(tree.root));
|
|
83
|
-
}
|
|
84
|
-
// All roots should be unique
|
|
85
|
-
for (let i = 0; i < roots.length; i++) {
|
|
86
|
-
for (let j = i + 1; j < roots.length; j++) {
|
|
87
|
-
assert_1.strict.notDeepEqual(roots[i], roots[j], `root ${i} and ${j} should differ`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
it("proof for non-existent index returns zero-leaf path elements", () => {
|
|
92
|
-
const tree = new src_1.MerkleTree(4);
|
|
93
|
-
const c = new Uint8Array(32).fill(0x01);
|
|
94
|
-
tree.insert(c);
|
|
95
|
-
// Index 0 has our commitment; index 1 was never inserted
|
|
96
|
-
const proof = tree.getPath(1);
|
|
97
|
-
assert_1.strict.ok(proof, "should return a path even for empty leaf");
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
// ---------------------------------------------------------------------------
|
|
101
|
-
// ExtData hash edge cases
|
|
102
|
-
// ---------------------------------------------------------------------------
|
|
103
|
-
describe("ExtData hash", () => {
|
|
104
|
-
it("zero fee and refund produce valid hash", () => {
|
|
105
|
-
const hash = (0, src_1.computeExtDataHash)({
|
|
106
|
-
recipient: web3_js_1.PublicKey.default,
|
|
107
|
-
relayer: web3_js_1.PublicKey.default,
|
|
108
|
-
fee: 0n,
|
|
109
|
-
refund: 0n,
|
|
110
|
-
claimant: web3_js_1.PublicKey.default,
|
|
111
|
-
});
|
|
112
|
-
assert_1.strict.equal(hash.length, 32);
|
|
113
|
-
});
|
|
114
|
-
it("different recipients produce different hashes", () => {
|
|
115
|
-
const base = {
|
|
116
|
-
relayer: web3_js_1.PublicKey.default,
|
|
117
|
-
fee: 100n,
|
|
118
|
-
refund: 0n,
|
|
119
|
-
claimant: web3_js_1.PublicKey.default,
|
|
120
|
-
};
|
|
121
|
-
const hash1 = (0, src_1.computeExtDataHash)({
|
|
122
|
-
...base,
|
|
123
|
-
recipient: web3_js_1.PublicKey.default,
|
|
124
|
-
});
|
|
125
|
-
const hash2 = (0, src_1.computeExtDataHash)({
|
|
126
|
-
...base,
|
|
127
|
-
recipient: new web3_js_1.PublicKey("11111111111111111111111111111112"),
|
|
128
|
-
});
|
|
129
|
-
assert_1.strict.notDeepEqual(hash1, hash2);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
// ---------------------------------------------------------------------------
|
|
133
|
-
// parseOnChainError
|
|
134
|
-
// ---------------------------------------------------------------------------
|
|
135
|
-
describe("parseOnChainError", () => {
|
|
136
|
-
it("maps known hex error code", () => {
|
|
137
|
-
const msg = (0, src_1.parseOnChainError)(new Error("custom program error: 0x1770"));
|
|
138
|
-
assert_1.strict.equal(msg, "The pool is temporarily paused. Please try again later.");
|
|
139
|
-
});
|
|
140
|
-
it("maps known decimal error number", () => {
|
|
141
|
-
const msg = (0, src_1.parseOnChainError)(new Error("Error Number: 6005"));
|
|
142
|
-
assert_1.strict.equal(msg, "These funds have already been spent.");
|
|
143
|
-
});
|
|
144
|
-
it("handles blockhash not found", () => {
|
|
145
|
-
const msg = (0, src_1.parseOnChainError)(new Error("Blockhash not found"));
|
|
146
|
-
assert_1.strict.ok(msg.includes("expired"));
|
|
147
|
-
});
|
|
148
|
-
it("handles insufficient funds", () => {
|
|
149
|
-
const msg = (0, src_1.parseOnChainError)(new Error("Insufficient funds for rent"));
|
|
150
|
-
assert_1.strict.ok(msg.includes("SOL"));
|
|
151
|
-
});
|
|
152
|
-
it("returns generic message for unknown errors", () => {
|
|
153
|
-
const msg = (0, src_1.parseOnChainError)(new Error("something completely unknown xyz"));
|
|
154
|
-
assert_1.strict.ok(msg.includes("could not be completed"));
|
|
155
|
-
});
|
|
156
|
-
it("handles null/undefined input", () => {
|
|
157
|
-
const msg = (0, src_1.parseOnChainError)(null);
|
|
158
|
-
assert_1.strict.ok(msg.includes("could not be completed"));
|
|
159
|
-
});
|
|
160
|
-
// Verify newly added codes
|
|
161
|
-
it("maps code 6001 (NoDenoms)", () => {
|
|
162
|
-
const msg = (0, src_1.parseOnChainError)(new Error("Error Number: 6001"));
|
|
163
|
-
assert_1.strict.ok(msg.includes("denominations"));
|
|
164
|
-
});
|
|
165
|
-
it("maps code 6044 (InvalidTreeId)", () => {
|
|
166
|
-
const msg = (0, src_1.parseOnChainError)(new Error("Error Number: 6044"));
|
|
167
|
-
assert_1.strict.ok(msg.includes("tree"));
|
|
168
|
-
});
|
|
169
|
-
it("maps code 6056 (JupiterInsufficientAccounts)", () => {
|
|
170
|
-
const msg = (0, src_1.parseOnChainError)(new Error("Error Number: 6056"));
|
|
171
|
-
assert_1.strict.ok(msg.includes("Jupiter"));
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
// ---------------------------------------------------------------------------
|
|
175
|
-
// withRpcRetry
|
|
176
|
-
// ---------------------------------------------------------------------------
|
|
177
|
-
describe("withRpcRetry", () => {
|
|
178
|
-
it("returns result on first success", async () => {
|
|
179
|
-
const result = await (0, src_1.withRpcRetry)(() => Promise.resolve("ok"));
|
|
180
|
-
assert_1.strict.equal(result, "ok");
|
|
181
|
-
});
|
|
182
|
-
it("retries on blockhash not found", async () => {
|
|
183
|
-
let calls = 0;
|
|
184
|
-
const result = await (0, src_1.withRpcRetry)(() => {
|
|
185
|
-
calls++;
|
|
186
|
-
if (calls < 3)
|
|
187
|
-
throw new Error("Blockhash not found");
|
|
188
|
-
return Promise.resolve("done");
|
|
189
|
-
}, { baseDelayMs: 10 });
|
|
190
|
-
assert_1.strict.equal(result, "done");
|
|
191
|
-
assert_1.strict.equal(calls, 3);
|
|
192
|
-
});
|
|
193
|
-
it("does not retry on program error", async () => {
|
|
194
|
-
let calls = 0;
|
|
195
|
-
try {
|
|
196
|
-
await (0, src_1.withRpcRetry)(() => {
|
|
197
|
-
calls++;
|
|
198
|
-
throw new Error("custom program error: 0x1770");
|
|
199
|
-
}, { baseDelayMs: 10 });
|
|
200
|
-
assert_1.strict.fail("should throw");
|
|
201
|
-
}
|
|
202
|
-
catch {
|
|
203
|
-
assert_1.strict.equal(calls, 1, "should not retry program errors");
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
it("gives up after maxRetries", async () => {
|
|
207
|
-
let calls = 0;
|
|
208
|
-
try {
|
|
209
|
-
await (0, src_1.withRpcRetry)(() => {
|
|
210
|
-
calls++;
|
|
211
|
-
throw new Error("503 Service Unavailable");
|
|
212
|
-
}, { maxRetries: 2, baseDelayMs: 10 });
|
|
213
|
-
assert_1.strict.fail("should throw");
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
assert_1.strict.equal(calls, 3, "should try 1 + 2 retries");
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "mocha";
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("mocha");
|
|
4
|
-
const assert_1 = require("assert");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
const src_1 = require("../src");
|
|
7
|
-
describe("Encryption helpers", function () {
|
|
8
|
-
this.timeout(10000);
|
|
9
|
-
before(async () => {
|
|
10
|
-
await (0, src_1.initPoseidon)();
|
|
11
|
-
});
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
// computeSignature
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
describe("computeSignature", () => {
|
|
16
|
-
it("returns a bigint in [0, BN254_FR_MODULUS)", () => {
|
|
17
|
-
const sig = (0, src_1.computeSignature)(1n, 2n, 3n);
|
|
18
|
-
assert_1.strict.ok(sig >= 0n && sig < src_1.BN254_FR_MODULUS);
|
|
19
|
-
});
|
|
20
|
-
it("is deterministic", () => {
|
|
21
|
-
assert_1.strict.equal((0, src_1.computeSignature)(1n, 2n, 3n), (0, src_1.computeSignature)(1n, 2n, 3n));
|
|
22
|
-
});
|
|
23
|
-
it("produces different output when private key changes", () => {
|
|
24
|
-
assert_1.strict.notEqual((0, src_1.computeSignature)(1n, 2n, 3n), (0, src_1.computeSignature)(99n, 2n, 3n));
|
|
25
|
-
});
|
|
26
|
-
it("produces different output when commitment changes", () => {
|
|
27
|
-
assert_1.strict.notEqual((0, src_1.computeSignature)(1n, 2n, 3n), (0, src_1.computeSignature)(1n, 99n, 3n));
|
|
28
|
-
});
|
|
29
|
-
it("produces different output when pathIndex changes", () => {
|
|
30
|
-
assert_1.strict.notEqual((0, src_1.computeSignature)(1n, 2n, 3n), (0, src_1.computeSignature)(1n, 2n, 99n));
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
// inputUTXOToCircuitFormat
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
describe("inputUTXOToCircuitFormat", () => {
|
|
37
|
-
it("converts pathElements from Uint8Array[] to bigint[]", () => {
|
|
38
|
-
const tree = new src_1.MerkleTree(4);
|
|
39
|
-
const kp = (0, src_1.generateKeypair)();
|
|
40
|
-
const utxo = (0, src_1.createOwnedUTXO)({
|
|
41
|
-
amount: 500n,
|
|
42
|
-
privateKey: kp.privateKey,
|
|
43
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
44
|
-
});
|
|
45
|
-
const { index } = tree.insert(utxo.commitment);
|
|
46
|
-
const { path } = tree.getPath(index);
|
|
47
|
-
const input = {
|
|
48
|
-
...utxo,
|
|
49
|
-
pathIndex: index,
|
|
50
|
-
pathElements: path,
|
|
51
|
-
privateKey: kp.privateKey,
|
|
52
|
-
};
|
|
53
|
-
const fmt = (0, src_1.inputUTXOToCircuitFormat)(input);
|
|
54
|
-
assert_1.strict.equal(fmt.amount, utxo.amount);
|
|
55
|
-
assert_1.strict.equal(fmt.pubkey, utxo.pubkey);
|
|
56
|
-
assert_1.strict.equal(fmt.blinding, utxo.blinding);
|
|
57
|
-
assert_1.strict.equal(fmt.pathIndex, index);
|
|
58
|
-
assert_1.strict.equal(fmt.privateKey, kp.privateKey);
|
|
59
|
-
assert_1.strict.equal(fmt.pathElements.length, path.length);
|
|
60
|
-
assert_1.strict.ok(fmt.pathElements.every((e) => typeof e === "bigint"));
|
|
61
|
-
});
|
|
62
|
-
it("reduces pathElements modulo BN254_FR_MODULUS", () => {
|
|
63
|
-
const tree = new src_1.MerkleTree(4);
|
|
64
|
-
const kp = (0, src_1.generateKeypair)();
|
|
65
|
-
const utxo = (0, src_1.createOwnedUTXO)({
|
|
66
|
-
amount: 0n,
|
|
67
|
-
privateKey: kp.privateKey,
|
|
68
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
69
|
-
});
|
|
70
|
-
const { index } = tree.insert(utxo.commitment);
|
|
71
|
-
const { path } = tree.getPath(index);
|
|
72
|
-
const input = {
|
|
73
|
-
...utxo,
|
|
74
|
-
pathIndex: index,
|
|
75
|
-
pathElements: path,
|
|
76
|
-
privateKey: kp.privateKey,
|
|
77
|
-
};
|
|
78
|
-
const fmt = (0, src_1.inputUTXOToCircuitFormat)(input);
|
|
79
|
-
assert_1.strict.ok(fmt.pathElements.every((e) => e < src_1.BN254_FR_MODULUS));
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
// ---------------------------------------------------------------------------
|
|
83
|
-
// deriveEncryptionKeypair
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
describe("deriveEncryptionKeypair", () => {
|
|
86
|
-
it("returns 32-byte public and secret keys", () => {
|
|
87
|
-
const kp = (0, src_1.deriveEncryptionKeypair)(12345n);
|
|
88
|
-
assert_1.strict.equal(kp.publicKey.length, 32);
|
|
89
|
-
assert_1.strict.equal(kp.secretKey.length, 32);
|
|
90
|
-
});
|
|
91
|
-
it("is deterministic", () => {
|
|
92
|
-
const kp1 = (0, src_1.deriveEncryptionKeypair)(12345n);
|
|
93
|
-
const kp2 = (0, src_1.deriveEncryptionKeypair)(12345n);
|
|
94
|
-
assert_1.strict.equal(Buffer.compare(Buffer.from(kp1.publicKey), Buffer.from(kp2.publicKey)), 0);
|
|
95
|
-
assert_1.strict.equal(Buffer.compare(Buffer.from(kp1.secretKey), Buffer.from(kp2.secretKey)), 0);
|
|
96
|
-
});
|
|
97
|
-
it("produces different keys for different private keys", () => {
|
|
98
|
-
const kp1 = (0, src_1.deriveEncryptionKeypair)(1n);
|
|
99
|
-
const kp2 = (0, src_1.deriveEncryptionKeypair)(2n);
|
|
100
|
-
assert_1.strict.notEqual(Buffer.compare(Buffer.from(kp1.publicKey), Buffer.from(kp2.publicKey)), 0);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
|
-
// encryptUTXONote / decryptUTXONote
|
|
105
|
-
// ---------------------------------------------------------------------------
|
|
106
|
-
describe("encryptUTXONote / decryptUTXONote round-trip", () => {
|
|
107
|
-
it("decrypts to the original UTXO", () => {
|
|
108
|
-
const kp = (0, src_1.generateKeypair)();
|
|
109
|
-
const utxo = (0, src_1.createOwnedUTXO)({
|
|
110
|
-
amount: 1000000n,
|
|
111
|
-
privateKey: kp.privateKey,
|
|
112
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
113
|
-
});
|
|
114
|
-
const utxoWithKey = { ...utxo, privateKey: kp.privateKey };
|
|
115
|
-
const recipientEncKp = (0, src_1.deriveEncryptionKeypair)(kp.privateKey);
|
|
116
|
-
const note = (0, src_1.encryptUTXONote)(utxoWithKey, recipientEncKp.publicKey);
|
|
117
|
-
const decrypted = (0, src_1.decryptUTXONote)(note, kp.privateKey, utxo.commitment, src_1.NATIVE_SOL_MINT);
|
|
118
|
-
assert_1.strict.ok(decrypted !== null, "decryption should succeed");
|
|
119
|
-
assert_1.strict.equal(decrypted.amount, utxo.amount);
|
|
120
|
-
assert_1.strict.equal(decrypted.blinding, utxo.blinding);
|
|
121
|
-
assert_1.strict.equal(decrypted.privateKey, kp.privateKey);
|
|
122
|
-
});
|
|
123
|
-
it("returns null when decrypting with the wrong private key", () => {
|
|
124
|
-
const kp = (0, src_1.generateKeypair)();
|
|
125
|
-
const utxo = (0, src_1.createOwnedUTXO)({
|
|
126
|
-
amount: 500n,
|
|
127
|
-
privateKey: kp.privateKey,
|
|
128
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
129
|
-
});
|
|
130
|
-
const utxoWithKey = { ...utxo, privateKey: kp.privateKey };
|
|
131
|
-
const recipientEncKp = (0, src_1.deriveEncryptionKeypair)(kp.privateKey);
|
|
132
|
-
const note = (0, src_1.encryptUTXONote)(utxoWithKey, recipientEncKp.publicKey);
|
|
133
|
-
const wrongKey = (0, src_1.generateKeypair)().privateKey;
|
|
134
|
-
const result = (0, src_1.decryptUTXONote)(note, wrongKey, utxo.commitment, src_1.NATIVE_SOL_MINT);
|
|
135
|
-
assert_1.strict.equal(result, null);
|
|
136
|
-
});
|
|
137
|
-
it("returns null when the commitment does not match", () => {
|
|
138
|
-
const kp = (0, src_1.generateKeypair)();
|
|
139
|
-
const utxo = (0, src_1.createOwnedUTXO)({
|
|
140
|
-
amount: 500n,
|
|
141
|
-
privateKey: kp.privateKey,
|
|
142
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
143
|
-
});
|
|
144
|
-
const utxo2 = (0, src_1.createOwnedUTXO)({
|
|
145
|
-
amount: 999n,
|
|
146
|
-
privateKey: kp.privateKey,
|
|
147
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
148
|
-
});
|
|
149
|
-
const utxoWithKey = { ...utxo, privateKey: kp.privateKey };
|
|
150
|
-
const recipientEncKp = (0, src_1.deriveEncryptionKeypair)(kp.privateKey);
|
|
151
|
-
const note = (0, src_1.encryptUTXONote)(utxoWithKey, recipientEncKp.publicKey);
|
|
152
|
-
const result = (0, src_1.decryptUTXONote)(note, kp.privateKey, utxo2.commitment, // wrong commitment
|
|
153
|
-
src_1.NATIVE_SOL_MINT);
|
|
154
|
-
assert_1.strict.equal(result, null);
|
|
155
|
-
});
|
|
156
|
-
it("each encryption is unique (nonce randomness)", () => {
|
|
157
|
-
const kp = (0, src_1.generateKeypair)();
|
|
158
|
-
const utxo = (0, src_1.createOwnedUTXO)({
|
|
159
|
-
amount: 1n,
|
|
160
|
-
privateKey: kp.privateKey,
|
|
161
|
-
mintAddress: src_1.NATIVE_SOL_MINT,
|
|
162
|
-
});
|
|
163
|
-
const utxoWithKey = { ...utxo, privateKey: kp.privateKey };
|
|
164
|
-
const recipientEncKp = (0, src_1.deriveEncryptionKeypair)(kp.privateKey);
|
|
165
|
-
const note1 = (0, src_1.encryptUTXONote)(utxoWithKey, recipientEncKp.publicKey);
|
|
166
|
-
const note2 = (0, src_1.encryptUTXONote)(utxoWithKey, recipientEncKp.publicKey);
|
|
167
|
-
// Different nonces / ephemeral keys
|
|
168
|
-
assert_1.strict.notEqual(Buffer.compare(Buffer.from(note1.nonce), Buffer.from(note2.nonce)), 0);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
// ---------------------------------------------------------------------------
|
|
172
|
-
// encryptBlindMailboxNote / decryptBlindMailboxNote
|
|
173
|
-
// ---------------------------------------------------------------------------
|
|
174
|
-
describe("encryptBlindMailboxNote / decryptBlindMailboxNote round-trip", () => {
|
|
175
|
-
function makeRecipient() {
|
|
176
|
-
return web3_js_1.Keypair.generate();
|
|
177
|
-
}
|
|
178
|
-
function makeNoteData() {
|
|
179
|
-
return {
|
|
180
|
-
blinding: new Uint8Array(32).fill(0xab),
|
|
181
|
-
leafIndex: 7,
|
|
182
|
-
commitment: new Uint8Array(32).fill(0xcd),
|
|
183
|
-
amount: 2500000n,
|
|
184
|
-
mintAddress: src_1.NATIVE_SOL_MINT.toBase58(),
|
|
185
|
-
treeId: 0,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
it("decrypts back to the original note data", () => {
|
|
189
|
-
const recipient = makeRecipient();
|
|
190
|
-
const noteData = makeNoteData();
|
|
191
|
-
const { ephemeralPublicKey, encryptedBlob } = (0, src_1.encryptBlindMailboxNote)(recipient.publicKey.toBytes(), noteData);
|
|
192
|
-
const decrypted = (0, src_1.decryptBlindMailboxNote)(recipient.secretKey, ephemeralPublicKey, encryptedBlob);
|
|
193
|
-
assert_1.strict.equal(decrypted.amount, noteData.amount);
|
|
194
|
-
assert_1.strict.equal(decrypted.leafIndex, noteData.leafIndex);
|
|
195
|
-
assert_1.strict.equal(decrypted.treeId, noteData.treeId);
|
|
196
|
-
assert_1.strict.equal(decrypted.mintAddress, noteData.mintAddress);
|
|
197
|
-
assert_1.strict.equal(Buffer.compare(Buffer.from(decrypted.blinding), Buffer.from(noteData.blinding)), 0);
|
|
198
|
-
assert_1.strict.equal(Buffer.compare(Buffer.from(decrypted.commitment), Buffer.from(noteData.commitment)), 0);
|
|
199
|
-
});
|
|
200
|
-
it("throws when decrypting with a different recipient key", () => {
|
|
201
|
-
const recipient1 = makeRecipient();
|
|
202
|
-
const recipient2 = makeRecipient();
|
|
203
|
-
const noteData = makeNoteData();
|
|
204
|
-
const { ephemeralPublicKey, encryptedBlob } = (0, src_1.encryptBlindMailboxNote)(recipient1.publicKey.toBytes(), noteData);
|
|
205
|
-
assert_1.strict.throws(() => (0, src_1.decryptBlindMailboxNote)(recipient2.secretKey, ephemeralPublicKey, encryptedBlob), /decryption failed/i);
|
|
206
|
-
});
|
|
207
|
-
it("each encryption produces a unique ephemeral key", () => {
|
|
208
|
-
const recipient = makeRecipient();
|
|
209
|
-
const noteData = makeNoteData();
|
|
210
|
-
const enc1 = (0, src_1.encryptBlindMailboxNote)(recipient.publicKey.toBytes(), noteData);
|
|
211
|
-
const enc2 = (0, src_1.encryptBlindMailboxNote)(recipient.publicKey.toBytes(), noteData);
|
|
212
|
-
assert_1.strict.notEqual(Buffer.compare(Buffer.from(enc1.ephemeralPublicKey), Buffer.from(enc2.ephemeralPublicKey)), 0);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "mocha";
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
require("mocha");
|
|
4
|
-
const assert_1 = require("assert");
|
|
5
|
-
const src_1 = require("../src");
|
|
6
|
-
/**
|
|
7
|
-
* Events module tests.
|
|
8
|
-
*
|
|
9
|
-
* scanCommitmentEvents / scanNullifierEvents / buildTreeFromEvents depend on
|
|
10
|
-
* live RPC, so here we test the tree-reconstruction logic they feed into and
|
|
11
|
-
* the type/shape contracts of the event types.
|
|
12
|
-
*/
|
|
13
|
-
describe("Events — tree reconstruction from commitment data", function () {
|
|
14
|
-
this.timeout(10000);
|
|
15
|
-
before(async () => {
|
|
16
|
-
await (0, src_1.initPoseidon)();
|
|
17
|
-
});
|
|
18
|
-
it("builds a tree from ordered commitments matching manual inserts", () => {
|
|
19
|
-
const depth = 8; // small tree for testing
|
|
20
|
-
const tree1 = new src_1.MerkleTree(depth);
|
|
21
|
-
const tree2 = new src_1.MerkleTree(depth);
|
|
22
|
-
// Simulate 5 commitment events with deterministic data
|
|
23
|
-
const commitments = [];
|
|
24
|
-
for (let i = 0; i < 5; i++) {
|
|
25
|
-
const c = new Uint8Array(32);
|
|
26
|
-
c[0] = i + 1;
|
|
27
|
-
c[31] = 0xff - i;
|
|
28
|
-
commitments.push(c);
|
|
29
|
-
}
|
|
30
|
-
// Insert in order (mimicking what buildTreeFromEvents does)
|
|
31
|
-
for (const c of commitments) {
|
|
32
|
-
tree1.insert(c);
|
|
33
|
-
tree2.insert(c);
|
|
34
|
-
}
|
|
35
|
-
assert_1.strict.deepEqual(tree1.root, tree2.root, "trees built identically should have the same root");
|
|
36
|
-
});
|
|
37
|
-
it("filters commitments by treeId correctly", () => {
|
|
38
|
-
const events = [
|
|
39
|
-
{ treeId: 0, leafIndex: 0, commitment: new Uint8Array(32).fill(1) },
|
|
40
|
-
{ treeId: 1, leafIndex: 0, commitment: new Uint8Array(32).fill(2) },
|
|
41
|
-
{ treeId: 0, leafIndex: 1, commitment: new Uint8Array(32).fill(3) },
|
|
42
|
-
{ treeId: 1, leafIndex: 1, commitment: new Uint8Array(32).fill(4) },
|
|
43
|
-
{ treeId: 0, leafIndex: 2, commitment: new Uint8Array(32).fill(5) },
|
|
44
|
-
];
|
|
45
|
-
const tree0Events = events
|
|
46
|
-
.filter((e) => e.treeId === 0)
|
|
47
|
-
.sort((a, b) => a.leafIndex - b.leafIndex);
|
|
48
|
-
assert_1.strict.equal(tree0Events.length, 3);
|
|
49
|
-
assert_1.strict.equal(tree0Events[0].leafIndex, 0);
|
|
50
|
-
assert_1.strict.equal(tree0Events[1].leafIndex, 1);
|
|
51
|
-
assert_1.strict.equal(tree0Events[2].leafIndex, 2);
|
|
52
|
-
const tree1Events = events
|
|
53
|
-
.filter((e) => e.treeId === 1)
|
|
54
|
-
.sort((a, b) => a.leafIndex - b.leafIndex);
|
|
55
|
-
assert_1.strict.equal(tree1Events.length, 2);
|
|
56
|
-
});
|
|
57
|
-
it("handles empty event list", () => {
|
|
58
|
-
const tree = new src_1.MerkleTree(8);
|
|
59
|
-
// No inserts — root should be the zero-leaf Merkle root
|
|
60
|
-
const root = tree.root;
|
|
61
|
-
assert_1.strict.equal(root.length, 32, "root should be 32 bytes");
|
|
62
|
-
});
|
|
63
|
-
it("reconstructed tree produces valid inclusion proofs", () => {
|
|
64
|
-
const tree = new src_1.MerkleTree(8);
|
|
65
|
-
const commitments = [];
|
|
66
|
-
for (let i = 0; i < 3; i++) {
|
|
67
|
-
const c = new Uint8Array(32);
|
|
68
|
-
c[0] = i + 10;
|
|
69
|
-
commitments.push(c);
|
|
70
|
-
tree.insert(c);
|
|
71
|
-
}
|
|
72
|
-
// Get proof for leaf 1
|
|
73
|
-
const proof = tree.getPath(1);
|
|
74
|
-
assert_1.strict.ok(proof, "should return a proof");
|
|
75
|
-
assert_1.strict.equal(proof.leafIndex, 1);
|
|
76
|
-
assert_1.strict.equal(proof.path.length, 8, "proof depth should match tree depth");
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "mocha";
|