@veilo/sdk-core 0.3.3 → 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 +289 -1262
- 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 +17 -912
- 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 +128 -0
- package/dist/cjs/compactNote.js +191 -0
- package/dist/cjs/events.d.ts +1 -1
- package/dist/cjs/events.js +2 -2
- package/dist/cjs/idl/privacy_pool.d.ts +5 -0
- package/dist/cjs/idl/privacy_pool.js +15218 -0
- package/dist/cjs/index.d.ts +17 -13
- package/dist/cjs/index.js +43 -30
- package/dist/cjs/merkle.d.ts +13 -0
- package/dist/cjs/merkle.js +31 -8
- 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/program.d.ts +11 -0
- package/dist/cjs/program.js +26 -3
- 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/proofs/types.js +2 -0
- package/dist/cjs/prover.d.ts +4 -1
- package/dist/cjs/prover.js +12 -2
- package/dist/cjs/random.d.ts +16 -0
- package/dist/cjs/random.js +28 -0
- 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/cjs/relayer/types.d.ts +276 -0
- package/dist/cjs/relayer/types.js +5 -0
- package/dist/cjs/relayer.d.ts +1 -295
- package/dist/cjs/relayer.js +15 -243
- package/dist/cjs/shield/alt.d.ts +87 -0
- package/dist/cjs/shield/alt.js +194 -0
- package/dist/cjs/shield/computeBudget.d.ts +61 -0
- package/dist/cjs/shield/computeBudget.js +64 -0
- package/dist/cjs/shield/errors.d.ts +58 -0
- package/dist/cjs/shield/errors.js +121 -0
- package/dist/cjs/shield/finalize.d.ts +45 -0
- package/dist/cjs/shield/finalize.js +119 -0
- package/dist/cjs/shield/index.d.ts +35 -0
- package/dist/cjs/shield/index.js +68 -0
- package/dist/cjs/shield/ix.d.ts +54 -0
- package/dist/cjs/shield/ix.js +119 -0
- package/dist/cjs/shield/owner.d.ts +36 -0
- package/dist/cjs/shield/owner.js +127 -0
- package/dist/cjs/shield/ports.d.ts +43 -0
- package/dist/cjs/shield/ports.js +153 -0
- package/dist/cjs/shield/preflight.d.ts +30 -0
- package/dist/cjs/shield/preflight.js +154 -0
- package/dist/cjs/shield/shield.d.ts +68 -0
- package/dist/cjs/shield/shield.js +500 -0
- package/dist/cjs/shield/types.d.ts +202 -0
- package/dist/cjs/shield/types.js +2 -0
- 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 -215
- package/dist/cjs/utxo.js +15 -391
- 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 -0
- package/dist/esm/client.js +3 -887
- 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 +128 -0
- package/dist/esm/compactNote.js +179 -0
- package/dist/esm/config.d.ts +82 -0
- package/dist/esm/events.d.ts +77 -0
- package/dist/esm/events.js +1 -1
- package/dist/esm/idl/privacy_pool.d.ts +5 -0
- package/dist/esm/idl/privacy_pool.js +15216 -0
- package/dist/esm/index.d.ts +17 -0
- package/dist/esm/index.js +20 -11
- package/dist/esm/merkle.d.ts +77 -0
- package/dist/esm/merkle.js +23 -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/package.json +1 -0
- package/dist/esm/poseidon.d.ts +29 -0
- package/dist/esm/program.d.ts +37 -0
- package/dist/esm/program.js +23 -1
- package/dist/esm/proof.d.ts +1 -0
- 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 +57 -0
- package/dist/esm/prover.js +10 -1
- package/dist/esm/random.d.ts +16 -0
- package/dist/esm/random.js +21 -0
- 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 -0
- package/dist/esm/relayer.js +2 -238
- package/dist/esm/retry.d.ts +32 -0
- package/dist/esm/shield/alt.d.ts +87 -0
- package/dist/esm/shield/alt.js +186 -0
- package/dist/esm/shield/computeBudget.d.ts +61 -0
- package/dist/esm/shield/computeBudget.js +61 -0
- package/dist/esm/shield/errors.d.ts +58 -0
- package/dist/esm/shield/errors.js +115 -0
- package/dist/esm/shield/finalize.d.ts +45 -0
- package/dist/esm/shield/finalize.js +83 -0
- package/dist/esm/shield/index.d.ts +35 -0
- package/dist/esm/shield/index.js +32 -0
- package/dist/esm/shield/ix.d.ts +54 -0
- package/dist/esm/shield/ix.js +82 -0
- package/dist/esm/shield/owner.d.ts +36 -0
- package/dist/esm/shield/owner.js +123 -0
- package/dist/esm/shield/ports.d.ts +43 -0
- package/dist/esm/shield/ports.js +147 -0
- package/dist/esm/shield/preflight.d.ts +30 -0
- package/dist/esm/shield/preflight.js +151 -0
- package/dist/esm/shield/shield.d.ts +68 -0
- package/dist/esm/shield/shield.js +493 -0
- package/dist/esm/shield/types.d.ts +202 -0
- package/dist/esm/shield/types.js +1 -0
- 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 -0
- package/dist/esm/utxo.js +2 -372
- package/package.json +111 -15
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet-agnostic shielding.
|
|
3
|
+
*
|
|
4
|
+
* `shield()` builds an unsigned transaction that deposits public funds into the
|
|
5
|
+
* privacy pool, creating a note owned by an arbitrary recipient. Any external
|
|
6
|
+
* wallet — a browser extension, or a third-party platform's managed wallet —
|
|
7
|
+
* signs and submits it. The SDK never touches a secret key.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* const owner = await resolveShieldOwner({ username: "alice" });
|
|
11
|
+
* const { transaction, note, proofCache } = await shield({
|
|
12
|
+
* connection, amount, mint, owner,
|
|
13
|
+
* signer: { publicKey: wallet.publicKey },
|
|
14
|
+
* prover: createTransactionProver(artifacts),
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* const signed = await wallet.signTransaction(transaction);
|
|
18
|
+
* const sig = await connection.sendRawTransaction(signed.serialize());
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* On blockhash expiry, `rebuild(result, { connection })` re-assembles with a
|
|
22
|
+
* fresh blockhash and deadline without re-proving.
|
|
23
|
+
*/
|
|
24
|
+
export { shield, rebuild, serializeProofCache, deserializeProofCache } from "./shield.js";
|
|
25
|
+
export { resolveShieldOwner, unsafeShieldOwner } from "./owner.js";
|
|
26
|
+
export { finalizeShield } from "./finalize.js";
|
|
27
|
+
export { preflightShield } from "./preflight.js";
|
|
28
|
+
export { buildTransactInstruction, TRANSACT_ACCOUNT_NAMES } from "./ix.js";
|
|
29
|
+
export type { TransactAccounts, TransactArgs } from "./ix.js";
|
|
30
|
+
export { sharedDepositAlt, explicitAlt, auditDepositAlt, expectedDepositAltKeys, requiredAltKeys, SHARED_DEPOSIT_ALT, SHARED_ALT_MINTS, } from "./alt.js";
|
|
31
|
+
export { onChainTreeSource, staticTreeSource, memoryCache, noCache } from "./ports.js";
|
|
32
|
+
export { ShieldError, mapShieldError, extractProgramCode, } from "./errors.js";
|
|
33
|
+
export type { ShieldErrorCode, ShieldRetryClass, ShieldErrorRemedy } from "./errors.js";
|
|
34
|
+
export { SHIELD_COMPUTE_UNIT_LIMIT, SHIELD_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS, SHIELD_COMPUTE_UNITS_MEASURED_TYPICAL, MAX_TRANSACTION_BYTES, SIGNATURE_BYTES, TRANSACT_INSTRUCTION_DATA_BYTES, NULLIFIER_MARKER_ACCOUNT_BYTES, NULLIFIER_MARKERS_PER_TRANSACT, DEFAULT_DEADLINE_SECONDS, } from "./computeBudget.js";
|
|
35
|
+
export type { ShieldOwner, ShieldSigner, ShieldParams, ShieldResult, ShieldNote, ShieldProofCache, ShieldQuote, TreeSource, AltSource, ShieldCachePort, DepositTarget, PreflightOptions, } from "./types.js";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wallet-agnostic shielding.
|
|
4
|
+
*
|
|
5
|
+
* `shield()` builds an unsigned transaction that deposits public funds into the
|
|
6
|
+
* privacy pool, creating a note owned by an arbitrary recipient. Any external
|
|
7
|
+
* wallet — a browser extension, or a third-party platform's managed wallet —
|
|
8
|
+
* signs and submits it. The SDK never touches a secret key.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const owner = await resolveShieldOwner({ username: "alice" });
|
|
12
|
+
* const { transaction, note, proofCache } = await shield({
|
|
13
|
+
* connection, amount, mint, owner,
|
|
14
|
+
* signer: { publicKey: wallet.publicKey },
|
|
15
|
+
* prover: createTransactionProver(artifacts),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const signed = await wallet.signTransaction(transaction);
|
|
19
|
+
* const sig = await connection.sendRawTransaction(signed.serialize());
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* On blockhash expiry, `rebuild(result, { connection })` re-assembles with a
|
|
23
|
+
* fresh blockhash and deadline without re-proving.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DEFAULT_DEADLINE_SECONDS = exports.NULLIFIER_MARKERS_PER_TRANSACT = exports.NULLIFIER_MARKER_ACCOUNT_BYTES = exports.TRANSACT_INSTRUCTION_DATA_BYTES = exports.SIGNATURE_BYTES = exports.MAX_TRANSACTION_BYTES = exports.SHIELD_COMPUTE_UNITS_MEASURED_TYPICAL = exports.SHIELD_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS = exports.SHIELD_COMPUTE_UNIT_LIMIT = exports.extractProgramCode = exports.mapShieldError = exports.ShieldError = exports.noCache = exports.memoryCache = exports.staticTreeSource = exports.onChainTreeSource = exports.SHARED_ALT_MINTS = exports.SHARED_DEPOSIT_ALT = exports.requiredAltKeys = exports.expectedDepositAltKeys = exports.auditDepositAlt = exports.explicitAlt = exports.sharedDepositAlt = exports.TRANSACT_ACCOUNT_NAMES = exports.buildTransactInstruction = exports.preflightShield = exports.finalizeShield = exports.unsafeShieldOwner = exports.resolveShieldOwner = exports.deserializeProofCache = exports.serializeProofCache = exports.rebuild = exports.shield = void 0;
|
|
27
|
+
var shield_js_1 = require("./shield.js");
|
|
28
|
+
Object.defineProperty(exports, "shield", { enumerable: true, get: function () { return shield_js_1.shield; } });
|
|
29
|
+
Object.defineProperty(exports, "rebuild", { enumerable: true, get: function () { return shield_js_1.rebuild; } });
|
|
30
|
+
Object.defineProperty(exports, "serializeProofCache", { enumerable: true, get: function () { return shield_js_1.serializeProofCache; } });
|
|
31
|
+
Object.defineProperty(exports, "deserializeProofCache", { enumerable: true, get: function () { return shield_js_1.deserializeProofCache; } });
|
|
32
|
+
var owner_js_1 = require("./owner.js");
|
|
33
|
+
Object.defineProperty(exports, "resolveShieldOwner", { enumerable: true, get: function () { return owner_js_1.resolveShieldOwner; } });
|
|
34
|
+
Object.defineProperty(exports, "unsafeShieldOwner", { enumerable: true, get: function () { return owner_js_1.unsafeShieldOwner; } });
|
|
35
|
+
var finalize_js_1 = require("./finalize.js");
|
|
36
|
+
Object.defineProperty(exports, "finalizeShield", { enumerable: true, get: function () { return finalize_js_1.finalizeShield; } });
|
|
37
|
+
var preflight_js_1 = require("./preflight.js");
|
|
38
|
+
Object.defineProperty(exports, "preflightShield", { enumerable: true, get: function () { return preflight_js_1.preflightShield; } });
|
|
39
|
+
var ix_js_1 = require("./ix.js");
|
|
40
|
+
Object.defineProperty(exports, "buildTransactInstruction", { enumerable: true, get: function () { return ix_js_1.buildTransactInstruction; } });
|
|
41
|
+
Object.defineProperty(exports, "TRANSACT_ACCOUNT_NAMES", { enumerable: true, get: function () { return ix_js_1.TRANSACT_ACCOUNT_NAMES; } });
|
|
42
|
+
var alt_js_1 = require("./alt.js");
|
|
43
|
+
Object.defineProperty(exports, "sharedDepositAlt", { enumerable: true, get: function () { return alt_js_1.sharedDepositAlt; } });
|
|
44
|
+
Object.defineProperty(exports, "explicitAlt", { enumerable: true, get: function () { return alt_js_1.explicitAlt; } });
|
|
45
|
+
Object.defineProperty(exports, "auditDepositAlt", { enumerable: true, get: function () { return alt_js_1.auditDepositAlt; } });
|
|
46
|
+
Object.defineProperty(exports, "expectedDepositAltKeys", { enumerable: true, get: function () { return alt_js_1.expectedDepositAltKeys; } });
|
|
47
|
+
Object.defineProperty(exports, "requiredAltKeys", { enumerable: true, get: function () { return alt_js_1.requiredAltKeys; } });
|
|
48
|
+
Object.defineProperty(exports, "SHARED_DEPOSIT_ALT", { enumerable: true, get: function () { return alt_js_1.SHARED_DEPOSIT_ALT; } });
|
|
49
|
+
Object.defineProperty(exports, "SHARED_ALT_MINTS", { enumerable: true, get: function () { return alt_js_1.SHARED_ALT_MINTS; } });
|
|
50
|
+
var ports_js_1 = require("./ports.js");
|
|
51
|
+
Object.defineProperty(exports, "onChainTreeSource", { enumerable: true, get: function () { return ports_js_1.onChainTreeSource; } });
|
|
52
|
+
Object.defineProperty(exports, "staticTreeSource", { enumerable: true, get: function () { return ports_js_1.staticTreeSource; } });
|
|
53
|
+
Object.defineProperty(exports, "memoryCache", { enumerable: true, get: function () { return ports_js_1.memoryCache; } });
|
|
54
|
+
Object.defineProperty(exports, "noCache", { enumerable: true, get: function () { return ports_js_1.noCache; } });
|
|
55
|
+
var errors_js_1 = require("./errors.js");
|
|
56
|
+
Object.defineProperty(exports, "ShieldError", { enumerable: true, get: function () { return errors_js_1.ShieldError; } });
|
|
57
|
+
Object.defineProperty(exports, "mapShieldError", { enumerable: true, get: function () { return errors_js_1.mapShieldError; } });
|
|
58
|
+
Object.defineProperty(exports, "extractProgramCode", { enumerable: true, get: function () { return errors_js_1.extractProgramCode; } });
|
|
59
|
+
var computeBudget_js_1 = require("./computeBudget.js");
|
|
60
|
+
Object.defineProperty(exports, "SHIELD_COMPUTE_UNIT_LIMIT", { enumerable: true, get: function () { return computeBudget_js_1.SHIELD_COMPUTE_UNIT_LIMIT; } });
|
|
61
|
+
Object.defineProperty(exports, "SHIELD_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS", { enumerable: true, get: function () { return computeBudget_js_1.SHIELD_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS; } });
|
|
62
|
+
Object.defineProperty(exports, "SHIELD_COMPUTE_UNITS_MEASURED_TYPICAL", { enumerable: true, get: function () { return computeBudget_js_1.SHIELD_COMPUTE_UNITS_MEASURED_TYPICAL; } });
|
|
63
|
+
Object.defineProperty(exports, "MAX_TRANSACTION_BYTES", { enumerable: true, get: function () { return computeBudget_js_1.MAX_TRANSACTION_BYTES; } });
|
|
64
|
+
Object.defineProperty(exports, "SIGNATURE_BYTES", { enumerable: true, get: function () { return computeBudget_js_1.SIGNATURE_BYTES; } });
|
|
65
|
+
Object.defineProperty(exports, "TRANSACT_INSTRUCTION_DATA_BYTES", { enumerable: true, get: function () { return computeBudget_js_1.TRANSACT_INSTRUCTION_DATA_BYTES; } });
|
|
66
|
+
Object.defineProperty(exports, "NULLIFIER_MARKER_ACCOUNT_BYTES", { enumerable: true, get: function () { return computeBudget_js_1.NULLIFIER_MARKER_ACCOUNT_BYTES; } });
|
|
67
|
+
Object.defineProperty(exports, "NULLIFIER_MARKERS_PER_TRANSACT", { enumerable: true, get: function () { return computeBudget_js_1.NULLIFIER_MARKERS_PER_TRANSACT; } });
|
|
68
|
+
Object.defineProperty(exports, "DEFAULT_DEADLINE_SECONDS", { enumerable: true, get: function () { return computeBudget_js_1.DEFAULT_DEADLINE_SECONDS; } });
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
2
|
+
import type { TransactionProofStruct } from "../proofs/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* `transact` instruction assembly, driven by the IDL rather than by a
|
|
5
|
+
* hand-written account list.
|
|
6
|
+
*
|
|
7
|
+
* Every existing deposit implementation spells out all sixteen accounts by hand
|
|
8
|
+
* in an `accountsStrict({...})` literal. That works until the IDL changes, at
|
|
9
|
+
* which point a silently misordered or missing account produces a runtime
|
|
10
|
+
* failure that is very hard to trace. Here the account list and the ordering
|
|
11
|
+
* come from the IDL itself, and an unresolved name throws at build time.
|
|
12
|
+
*
|
|
13
|
+
* Building the instruction directly also means no Anchor `Provider` and no
|
|
14
|
+
* `Wallet` — which is the whole point of a wallet-agnostic shield.
|
|
15
|
+
*/
|
|
16
|
+
/** Account names the IDL declares for `transact`, in order. */
|
|
17
|
+
export type TransactAccounts = Record<string, PublicKey>;
|
|
18
|
+
export type TransactArgs = {
|
|
19
|
+
root: Uint8Array;
|
|
20
|
+
inputTreeId: number;
|
|
21
|
+
outputTreeId: number;
|
|
22
|
+
publicAmount: bigint;
|
|
23
|
+
extDataHash: Uint8Array;
|
|
24
|
+
mintAddress: PublicKey;
|
|
25
|
+
inputNullifiers: [Uint8Array, Uint8Array];
|
|
26
|
+
outputCommitments: [Uint8Array, Uint8Array];
|
|
27
|
+
deadline: bigint;
|
|
28
|
+
extData: {
|
|
29
|
+
recipient: PublicKey;
|
|
30
|
+
relayer: PublicKey;
|
|
31
|
+
fee: bigint;
|
|
32
|
+
refund: bigint;
|
|
33
|
+
claimant: PublicKey;
|
|
34
|
+
};
|
|
35
|
+
proof: TransactionProofStruct;
|
|
36
|
+
noteCiphers: {
|
|
37
|
+
note0EphemeralKey: Uint8Array;
|
|
38
|
+
note0Encrypted: Uint8Array;
|
|
39
|
+
note0ViewTag: number;
|
|
40
|
+
note1EphemeralKey: Uint8Array;
|
|
41
|
+
note1Encrypted: Uint8Array;
|
|
42
|
+
note1ViewTag: number;
|
|
43
|
+
} | null;
|
|
44
|
+
};
|
|
45
|
+
/** Account names in IDL order. Exported so callers can see what must be resolved. */
|
|
46
|
+
export declare const TRANSACT_ACCOUNT_NAMES: string[];
|
|
47
|
+
/**
|
|
48
|
+
* Build the `transact` instruction.
|
|
49
|
+
*
|
|
50
|
+
* @throws ShieldError('UNRESOLVED_ACCOUNT') if the IDL declares an account the
|
|
51
|
+
* caller did not supply — a loud failure is the point, because the
|
|
52
|
+
* alternative is a misordered account list that fails opaquely on-chain.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildTransactInstruction(accounts: TransactAccounts, args: TransactArgs, programId?: PublicKey): TransactionInstruction;
|
|
@@ -0,0 +1,119 @@
|
|
|
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.TRANSACT_ACCOUNT_NAMES = void 0;
|
|
37
|
+
exports.buildTransactInstruction = buildTransactInstruction;
|
|
38
|
+
const anchor = __importStar(require("@coral-xyz/anchor"));
|
|
39
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
40
|
+
const program_js_1 = require("../program.js");
|
|
41
|
+
const errors_js_1 = require("./errors.js");
|
|
42
|
+
const computeBudget_js_1 = require("./computeBudget.js");
|
|
43
|
+
// Anchor is CommonJS and does not expose BN as a detectable named export to
|
|
44
|
+
// Node ESM. Pull both runtime values from the namespace so CJS and ESM agree.
|
|
45
|
+
const { BN, BorshInstructionCoder } = anchor;
|
|
46
|
+
const IDL_TRANSACT = program_js_1.PRIVACY_POOL_IDL.instructions.find((i) => i.name === "transact");
|
|
47
|
+
if (!IDL_TRANSACT) {
|
|
48
|
+
throw new Error("privacy_pool IDL has no `transact` instruction");
|
|
49
|
+
}
|
|
50
|
+
/** Account names in IDL order. Exported so callers can see what must be resolved. */
|
|
51
|
+
exports.TRANSACT_ACCOUNT_NAMES = IDL_TRANSACT.accounts.map((a) => a.name);
|
|
52
|
+
/**
|
|
53
|
+
* Build the `transact` instruction.
|
|
54
|
+
*
|
|
55
|
+
* @throws ShieldError('UNRESOLVED_ACCOUNT') if the IDL declares an account the
|
|
56
|
+
* caller did not supply — a loud failure is the point, because the
|
|
57
|
+
* alternative is a misordered account list that fails opaquely on-chain.
|
|
58
|
+
*/
|
|
59
|
+
function buildTransactInstruction(accounts, args, programId = program_js_1.PRIVACY_POOL_PROGRAM_ID) {
|
|
60
|
+
const keys = IDL_TRANSACT.accounts.map((a) => {
|
|
61
|
+
const pubkey = accounts[a.name];
|
|
62
|
+
if (!pubkey) {
|
|
63
|
+
throw new errors_js_1.ShieldError("UNRESOLVED_ACCOUNT", `The IDL declares account "${a.name}" for transact, but it was not resolved. ` +
|
|
64
|
+
`Expected accounts: ${exports.TRANSACT_ACCOUNT_NAMES.join(", ")}`, { context: { missing: a.name, supplied: Object.keys(accounts) } });
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
pubkey,
|
|
68
|
+
isWritable: !!a.writable,
|
|
69
|
+
isSigner: !!a.signer,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
const coder = new BorshInstructionCoder(program_js_1.PRIVACY_POOL_IDL);
|
|
73
|
+
const data = coder.encode("transact", toBorshArgs(args));
|
|
74
|
+
if (data.length !== computeBudget_js_1.TRANSACT_INSTRUCTION_DATA_BYTES) {
|
|
75
|
+
// Not fatal — the size budget assertion downstream is authoritative — but a
|
|
76
|
+
// change here means the size arithmetic in computeBudget.ts is stale.
|
|
77
|
+
console.warn(`[veilo] transact instruction data is ${data.length} bytes, expected ` +
|
|
78
|
+
`${computeBudget_js_1.TRANSACT_INSTRUCTION_DATA_BYTES}. The shield size budget may no longer hold.`);
|
|
79
|
+
}
|
|
80
|
+
return new web3_js_1.TransactionInstruction({ programId, keys, data });
|
|
81
|
+
}
|
|
82
|
+
/** Anchor's Borsh coder wants camelCase field names, BNs, and plain arrays. */
|
|
83
|
+
function toBorshArgs(args) {
|
|
84
|
+
return {
|
|
85
|
+
root: Array.from(args.root),
|
|
86
|
+
input_tree_id: args.inputTreeId,
|
|
87
|
+
output_tree_id: args.outputTreeId,
|
|
88
|
+
public_amount: new BN(args.publicAmount.toString()),
|
|
89
|
+
ext_data_hash: Array.from(args.extDataHash),
|
|
90
|
+
mint_address: args.mintAddress,
|
|
91
|
+
input_nullifier_0: Array.from(args.inputNullifiers[0]),
|
|
92
|
+
input_nullifier_1: Array.from(args.inputNullifiers[1]),
|
|
93
|
+
output_commitment_0: Array.from(args.outputCommitments[0]),
|
|
94
|
+
output_commitment_1: Array.from(args.outputCommitments[1]),
|
|
95
|
+
deadline: new BN(args.deadline.toString()),
|
|
96
|
+
ext_data: {
|
|
97
|
+
recipient: args.extData.recipient,
|
|
98
|
+
relayer: args.extData.relayer,
|
|
99
|
+
fee: new BN(args.extData.fee.toString()),
|
|
100
|
+
refund: new BN(args.extData.refund.toString()),
|
|
101
|
+
claimant: args.extData.claimant,
|
|
102
|
+
},
|
|
103
|
+
proof: {
|
|
104
|
+
proof_a: args.proof.proofA,
|
|
105
|
+
proof_b: args.proof.proofB,
|
|
106
|
+
proof_c: args.proof.proofC,
|
|
107
|
+
},
|
|
108
|
+
note_ciphers: args.noteCiphers
|
|
109
|
+
? {
|
|
110
|
+
note0_ephemeral_key: Array.from(args.noteCiphers.note0EphemeralKey),
|
|
111
|
+
note0_encrypted: Array.from(args.noteCiphers.note0Encrypted),
|
|
112
|
+
note0_view_tag: args.noteCiphers.note0ViewTag,
|
|
113
|
+
note1_ephemeral_key: Array.from(args.noteCiphers.note1EphemeralKey),
|
|
114
|
+
note1_encrypted: Array.from(args.noteCiphers.note1Encrypted),
|
|
115
|
+
note1_view_tag: args.noteCiphers.note1ViewTag,
|
|
116
|
+
}
|
|
117
|
+
: null,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import type { ShieldOwner } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a shield recipient into the pair of keys that must belong to the same
|
|
5
|
+
* account.
|
|
6
|
+
*
|
|
7
|
+
* This is the only mechanism that makes the owner invariant safe. A note's
|
|
8
|
+
* *spend* authority is a Poseidon field element and its *detection* authority is
|
|
9
|
+
* an Ed25519 wallet key; nothing on-chain relates them, and if an integrator
|
|
10
|
+
* sources them separately and gets them wrong, the note is spendable but
|
|
11
|
+
* permanently invisible — the funds are gone from the owner's view with no error
|
|
12
|
+
* raised anywhere in the stack.
|
|
13
|
+
*
|
|
14
|
+
* `GET /auth/veiloPublicKey` returns both halves in a single response, so
|
|
15
|
+
* routing through this function makes the pairing structural rather than a
|
|
16
|
+
* convention integrators are asked to remember.
|
|
17
|
+
*
|
|
18
|
+
* Prefer this over hand-building a {@link ShieldOwner} in all cases.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveShieldOwner(target: {
|
|
21
|
+
username: string;
|
|
22
|
+
} | {
|
|
23
|
+
publicKey: string | PublicKey;
|
|
24
|
+
}): Promise<ShieldOwner>;
|
|
25
|
+
/**
|
|
26
|
+
* Build a {@link ShieldOwner} from keys the caller already holds.
|
|
27
|
+
*
|
|
28
|
+
* Only correct when both keys provably belong to the same account. The explicit
|
|
29
|
+
* flag is not ceremony — it is the last checkpoint before a class of bug whose
|
|
30
|
+
* only symptom is a user's money quietly disappearing from their balance.
|
|
31
|
+
*/
|
|
32
|
+
export declare function unsafeShieldOwner(params: {
|
|
33
|
+
veiloPublicKey: bigint;
|
|
34
|
+
noteViewingKey: PublicKey;
|
|
35
|
+
acknowledgeOwnerInvariant: true;
|
|
36
|
+
}): ShieldOwner;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveShieldOwner = resolveShieldOwner;
|
|
4
|
+
exports.unsafeShieldOwner = unsafeShieldOwner;
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const client_js_1 = require("../relayer/client.js");
|
|
7
|
+
const errors_js_1 = require("../relayer/errors.js");
|
|
8
|
+
const errors_js_2 = require("./errors.js");
|
|
9
|
+
/**
|
|
10
|
+
* Owner resolution is a Veilo protocol service, not an integrator-selected
|
|
11
|
+
* transport. Keep the production endpoint and public encryption key inside the
|
|
12
|
+
* SDK so callers cannot accidentally resolve the two owner keys from different
|
|
13
|
+
* relayers.
|
|
14
|
+
*
|
|
15
|
+
* These values are public network coordinates, not credentials. In particular,
|
|
16
|
+
* never put a secret API key here: browser/mobile package contents are always
|
|
17
|
+
* inspectable. The two owner endpoints used below are intentionally public and
|
|
18
|
+
* return public key material only.
|
|
19
|
+
*/
|
|
20
|
+
const OWNER_RELAYER = new client_js_1.VeiloRelayerClient({
|
|
21
|
+
apiKey: "",
|
|
22
|
+
relayerPublicKey: "utVxnA7zax09qJCZ7UJsa8PAOoWLRcCwOkdxg/ZGmD4=",
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a shield recipient into the pair of keys that must belong to the same
|
|
26
|
+
* account.
|
|
27
|
+
*
|
|
28
|
+
* This is the only mechanism that makes the owner invariant safe. A note's
|
|
29
|
+
* *spend* authority is a Poseidon field element and its *detection* authority is
|
|
30
|
+
* an Ed25519 wallet key; nothing on-chain relates them, and if an integrator
|
|
31
|
+
* sources them separately and gets them wrong, the note is spendable but
|
|
32
|
+
* permanently invisible — the funds are gone from the owner's view with no error
|
|
33
|
+
* raised anywhere in the stack.
|
|
34
|
+
*
|
|
35
|
+
* `GET /auth/veiloPublicKey` returns both halves in a single response, so
|
|
36
|
+
* routing through this function makes the pairing structural rather than a
|
|
37
|
+
* convention integrators are asked to remember.
|
|
38
|
+
*
|
|
39
|
+
* Prefer this over hand-building a {@link ShieldOwner} in all cases.
|
|
40
|
+
*/
|
|
41
|
+
async function resolveShieldOwner(target) {
|
|
42
|
+
const query = "username" in target
|
|
43
|
+
? { username: target.username }
|
|
44
|
+
: {
|
|
45
|
+
publicKey: typeof target.publicKey === "string"
|
|
46
|
+
? target.publicKey
|
|
47
|
+
: target.publicKey.toBase58(),
|
|
48
|
+
};
|
|
49
|
+
let response;
|
|
50
|
+
try {
|
|
51
|
+
response = await OWNER_RELAYER.getVeiloPublicKey(query);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
// A raw Solana address may not have a Veilo account yet. Provisioning is
|
|
55
|
+
// public and idempotent, and returns only the Poseidon spend key; the
|
|
56
|
+
// address we were given is the matching note-viewing key.
|
|
57
|
+
if ("publicKey" in target &&
|
|
58
|
+
(e?.status === 404 || (e instanceof errors_js_1.VeiloApiError && e.status === 404))) {
|
|
59
|
+
const wallet = typeof target.publicKey === "string"
|
|
60
|
+
? new web3_js_1.PublicKey(target.publicKey)
|
|
61
|
+
: target.publicKey;
|
|
62
|
+
const provisioned = await OWNER_RELAYER.preRegisterKey(wallet.toBase58());
|
|
63
|
+
if (!provisioned?.veiloPublicKey) {
|
|
64
|
+
throw new errors_js_2.ShieldError("UNKNOWN", "The relayer pre-registered the recipient but returned no Veilo public key.", { context: { publicKey: wallet.toBase58(), response: provisioned }, cause: e });
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
veiloPublicKey: BigInt(provisioned.veiloPublicKey),
|
|
68
|
+
noteViewingKey: wallet,
|
|
69
|
+
acknowledgeOwnerInvariant: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// A pre-registered account is one someone else created on the recipient's
|
|
73
|
+
// behalf; the recipient has never proved ownership, so the relayer refuses
|
|
74
|
+
// to resolve it by username. Shielding to them still works, but the caller
|
|
75
|
+
// must address them by Solana address instead.
|
|
76
|
+
if (e?.body?.preRegistered ||
|
|
77
|
+
e?.details?.preRegistered ||
|
|
78
|
+
/preregistered/i.test(String(e?.message ?? ""))) {
|
|
79
|
+
throw new errors_js_2.ShieldError("UNKNOWN", `"${"username" in target ? target.username : "that account"}" is pre-registered ` +
|
|
80
|
+
`and cannot be resolved by username. Resolve it by Solana address instead — ` +
|
|
81
|
+
`resolveShieldOwner({ publicKey }).`, { context: { preRegistered: true }, cause: e });
|
|
82
|
+
}
|
|
83
|
+
throw e;
|
|
84
|
+
}
|
|
85
|
+
const veiloPublicKeyRaw = response?.veiloPublicKey;
|
|
86
|
+
const walletRaw = response?.pubK;
|
|
87
|
+
if (!veiloPublicKeyRaw || !walletRaw) {
|
|
88
|
+
throw new errors_js_2.ShieldError("UNKNOWN", `The relayer did not return both keys for this recipient ` +
|
|
89
|
+
`(veiloPublicKey=${!!veiloPublicKeyRaw}, pubK=${!!walletRaw}). ` +
|
|
90
|
+
`Shielding without both would create a note the owner cannot find.`, { context: { response } });
|
|
91
|
+
}
|
|
92
|
+
const noteViewingKey = new web3_js_1.PublicKey(walletRaw);
|
|
93
|
+
if ("publicKey" in target &&
|
|
94
|
+
!noteViewingKey.equals(typeof target.publicKey === "string"
|
|
95
|
+
? new web3_js_1.PublicKey(target.publicKey)
|
|
96
|
+
: target.publicKey)) {
|
|
97
|
+
throw new errors_js_2.ShieldError("UNKNOWN", "The Veilo owner service returned a different wallet than the one requested. " +
|
|
98
|
+
"Shielding was stopped to prevent creating a note for the wrong recipient.", {
|
|
99
|
+
context: {
|
|
100
|
+
requested: typeof target.publicKey === "string"
|
|
101
|
+
? target.publicKey
|
|
102
|
+
: target.publicKey.toBase58(),
|
|
103
|
+
returned: noteViewingKey.toBase58(),
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
veiloPublicKey: BigInt(veiloPublicKeyRaw),
|
|
109
|
+
noteViewingKey,
|
|
110
|
+
// Safe to assert: both halves came from one response about one account.
|
|
111
|
+
acknowledgeOwnerInvariant: true,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build a {@link ShieldOwner} from keys the caller already holds.
|
|
116
|
+
*
|
|
117
|
+
* Only correct when both keys provably belong to the same account. The explicit
|
|
118
|
+
* flag is not ceremony — it is the last checkpoint before a class of bug whose
|
|
119
|
+
* only symptom is a user's money quietly disappearing from their balance.
|
|
120
|
+
*/
|
|
121
|
+
function unsafeShieldOwner(params) {
|
|
122
|
+
return {
|
|
123
|
+
veiloPublicKey: params.veiloPublicKey,
|
|
124
|
+
noteViewingKey: params.noteViewingKey,
|
|
125
|
+
acknowledgeOwnerInvariant: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
2
|
+
import type { DepositTarget, ShieldCachePort, TreeSource } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Injection points for the shield path.
|
|
5
|
+
*
|
|
6
|
+
* The three production deposit implementations (extension, wallet-app,
|
|
7
|
+
* veilo-dapp) are ~85% identical and diverge on exactly these axes: where
|
|
8
|
+
* proofs come from, where the tree comes from, which lookup table to use, and
|
|
9
|
+
* what to cache into. Making each an explicit port is what lets one
|
|
10
|
+
* implementation serve all of them — and lets a third-party integrator supply
|
|
11
|
+
* their own without forking anything.
|
|
12
|
+
*
|
|
13
|
+
* Proof generation is deliberately NOT redefined here: `TransactionProofBuilder`
|
|
14
|
+
* from `proof.ts` already has the right shape, and a second prover abstraction
|
|
15
|
+
* would be exactly the kind of duplication this module exists to avoid.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Read the target tree and root directly from chain.
|
|
19
|
+
*
|
|
20
|
+
* Note the account decoding: `MerkleTreeAccount::EXPECTED_SIZE` (9107) does not
|
|
21
|
+
* match the size its declared fields sum to (8987), a 120-byte discrepancy that
|
|
22
|
+
* is unexplained. Until it is, hand-slicing this account at fixed byte offsets
|
|
23
|
+
* is unsafe. Anchor's coder reads declared fields from the front and ignores the
|
|
24
|
+
* tail, so `.fetch()` stays correct regardless.
|
|
25
|
+
*/
|
|
26
|
+
export declare function onChainTreeSource(connection: Connection, programId?: PublicKey): TreeSource;
|
|
27
|
+
/**
|
|
28
|
+
* Fixed values, for tests and offline builds.
|
|
29
|
+
*
|
|
30
|
+
* Also the escape hatch for an integrator who already tracks the tree state and
|
|
31
|
+
* does not want the SDK making RPC calls on their behalf.
|
|
32
|
+
*/
|
|
33
|
+
export declare function staticTreeSource(target: DepositTarget): TreeSource;
|
|
34
|
+
/**
|
|
35
|
+
* In-memory cache with TTL. The default.
|
|
36
|
+
*
|
|
37
|
+
* Persistent storage is deliberately the caller's problem — `localStorage`,
|
|
38
|
+
* `chrome.storage`, and `AsyncStorage` are three different answers in three
|
|
39
|
+
* different apps, and none of them belongs in a published SDK.
|
|
40
|
+
*/
|
|
41
|
+
export declare function memoryCache(): ShieldCachePort;
|
|
42
|
+
/** A cache that never stores anything. Useful for tests that assert fetch counts. */
|
|
43
|
+
export declare function noCache(): ShieldCachePort;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.onChainTreeSource = onChainTreeSource;
|
|
4
|
+
exports.staticTreeSource = staticTreeSource;
|
|
5
|
+
exports.memoryCache = memoryCache;
|
|
6
|
+
exports.noCache = noCache;
|
|
7
|
+
const program_js_1 = require("../program.js");
|
|
8
|
+
const pdas_js_1 = require("../accounts/pdas.js");
|
|
9
|
+
const config_js_1 = require("../config.js");
|
|
10
|
+
const errors_js_1 = require("./errors.js");
|
|
11
|
+
/**
|
|
12
|
+
* Injection points for the shield path.
|
|
13
|
+
*
|
|
14
|
+
* The three production deposit implementations (extension, wallet-app,
|
|
15
|
+
* veilo-dapp) are ~85% identical and diverge on exactly these axes: where
|
|
16
|
+
* proofs come from, where the tree comes from, which lookup table to use, and
|
|
17
|
+
* what to cache into. Making each an explicit port is what lets one
|
|
18
|
+
* implementation serve all of them — and lets a third-party integrator supply
|
|
19
|
+
* their own without forking anything.
|
|
20
|
+
*
|
|
21
|
+
* Proof generation is deliberately NOT redefined here: `TransactionProofBuilder`
|
|
22
|
+
* from `proof.ts` already has the right shape, and a second prover abstraction
|
|
23
|
+
* would be exactly the kind of duplication this module exists to avoid.
|
|
24
|
+
*/
|
|
25
|
+
// -- TreeSource ---------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Read the target tree and root directly from chain.
|
|
28
|
+
*
|
|
29
|
+
* Note the account decoding: `MerkleTreeAccount::EXPECTED_SIZE` (9107) does not
|
|
30
|
+
* match the size its declared fields sum to (8987), a 120-byte discrepancy that
|
|
31
|
+
* is unexplained. Until it is, hand-slicing this account at fixed byte offsets
|
|
32
|
+
* is unsafe. Anchor's coder reads declared fields from the front and ignores the
|
|
33
|
+
* tail, so `.fetch()` stays correct regardless.
|
|
34
|
+
*/
|
|
35
|
+
function onChainTreeSource(connection, programId = program_js_1.PRIVACY_POOL_PROGRAM_ID) {
|
|
36
|
+
return {
|
|
37
|
+
async getDepositTarget(mint) {
|
|
38
|
+
const program = (0, program_js_1.createReadonlyVeiloProgram)(connection);
|
|
39
|
+
const { config } = (0, pdas_js_1.getPoolPdas)(programId, mint);
|
|
40
|
+
const cfg = await program.account.privacyConfig.fetch(config);
|
|
41
|
+
const numTrees = Number(cfg.numTrees);
|
|
42
|
+
if (!Number.isInteger(numTrees) || numTrees <= 0) {
|
|
43
|
+
throw new errors_js_1.ShieldError("TREE_FULL", `Pool ${mint.toBase58()} has no deposit tree.`, { context: { mint: mint.toBase58(), numTrees } });
|
|
44
|
+
}
|
|
45
|
+
// Fetch every tree in one RPC call. The older getBestTreeForDeposit path
|
|
46
|
+
// fetched them serially, then fetched the chosen trees a second time.
|
|
47
|
+
const treePdas = Array.from({ length: numTrees }, (_, treeId) => (0, pdas_js_1.getNoteTreePda)(programId, mint, treeId));
|
|
48
|
+
const infos = await connection.getMultipleAccountsInfo(treePdas, {
|
|
49
|
+
commitment: "confirmed",
|
|
50
|
+
});
|
|
51
|
+
const capacity = 2 ** config_js_1.MERKLE_TREE_DEPTH;
|
|
52
|
+
const trees = infos.map((info, treeId) => {
|
|
53
|
+
if (!info)
|
|
54
|
+
return null;
|
|
55
|
+
// Anchor camel-cases the IDL's `MerkleTreeAccount` name when it builds
|
|
56
|
+
// the Borsh account-layout map (the same key exposed as
|
|
57
|
+
// `program.account.merkleTreeAccount`).
|
|
58
|
+
const decoded = program.coder.accounts.decode("merkleTreeAccount", info.data);
|
|
59
|
+
const nextIndex = Number(decoded.nextIndex);
|
|
60
|
+
return {
|
|
61
|
+
treeId,
|
|
62
|
+
decoded,
|
|
63
|
+
nextIndex,
|
|
64
|
+
remainingCapacity: capacity - nextIndex,
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
const inputTree = trees[0];
|
|
68
|
+
if (!inputTree) {
|
|
69
|
+
throw new errors_js_1.ShieldError("POOL_NOT_FOUND", `Pool ${mint.toBase58()} is missing its input Merkle tree (tree 0).`, { context: { mint: mint.toBase58(), tree: treePdas[0].toBase58() } });
|
|
70
|
+
}
|
|
71
|
+
const available = trees.filter((tree) => !!tree && tree.nextIndex < capacity);
|
|
72
|
+
if (available.length === 0) {
|
|
73
|
+
throw new errors_js_1.ShieldError("TREE_FULL", `All ${numTrees} Merkle trees for ${mint.toBase58()} are full.`, { context: { mint: mint.toBase58(), numTrees, capacity } });
|
|
74
|
+
}
|
|
75
|
+
const minCapacity = Math.floor(capacity * 0.0001);
|
|
76
|
+
const preferred = available
|
|
77
|
+
.filter((tree) => tree.remainingCapacity >= minCapacity)
|
|
78
|
+
.sort((a, b) => a.treeId - b.treeId);
|
|
79
|
+
const outputTree = preferred[0] ??
|
|
80
|
+
available.sort((a, b) => b.remainingCapacity - a.remainingCapacity)[0];
|
|
81
|
+
return {
|
|
82
|
+
inputTreeId: 0,
|
|
83
|
+
inputRoot: extractRoot(inputTree.decoded),
|
|
84
|
+
outputTreeId: outputTree.treeId,
|
|
85
|
+
outputNextIndex: outputTree.nextIndex,
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Fixed values, for tests and offline builds.
|
|
92
|
+
*
|
|
93
|
+
* Also the escape hatch for an integrator who already tracks the tree state and
|
|
94
|
+
* does not want the SDK making RPC calls on their behalf.
|
|
95
|
+
*/
|
|
96
|
+
function staticTreeSource(target) {
|
|
97
|
+
return { async getDepositTarget() { return target; } };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Read the root from a decoded `MerkleTreeAccount`.
|
|
101
|
+
*
|
|
102
|
+
* Uses `root_history[root_index]` rather than the `root` field. Both are written
|
|
103
|
+
* to the same value by `append` (merkle_tree.rs:108-111) so they agree, but the
|
|
104
|
+
* history read is what all three production implementations use and is therefore
|
|
105
|
+
* the one that is actually exercised against mainnet.
|
|
106
|
+
*/
|
|
107
|
+
function extractRoot(tree) {
|
|
108
|
+
const history = tree.rootHistory ?? tree.root_history;
|
|
109
|
+
const index = Number(tree.rootIndex ?? tree.root_index ?? 0);
|
|
110
|
+
if (Array.isArray(history) && history[index]) {
|
|
111
|
+
return new Uint8Array(history[index]);
|
|
112
|
+
}
|
|
113
|
+
const root = tree.root;
|
|
114
|
+
if (root)
|
|
115
|
+
return new Uint8Array(root);
|
|
116
|
+
throw new Error("could not read a Merkle root from the tree account");
|
|
117
|
+
}
|
|
118
|
+
// -- Cache --------------------------------------------------------------------
|
|
119
|
+
/**
|
|
120
|
+
* In-memory cache with TTL. The default.
|
|
121
|
+
*
|
|
122
|
+
* Persistent storage is deliberately the caller's problem — `localStorage`,
|
|
123
|
+
* `chrome.storage`, and `AsyncStorage` are three different answers in three
|
|
124
|
+
* different apps, and none of them belongs in a published SDK.
|
|
125
|
+
*/
|
|
126
|
+
function memoryCache() {
|
|
127
|
+
const store = new Map();
|
|
128
|
+
return {
|
|
129
|
+
async get(key) {
|
|
130
|
+
const hit = store.get(key);
|
|
131
|
+
if (!hit)
|
|
132
|
+
return undefined;
|
|
133
|
+
if (hit.expiresAt !== 0 && hit.expiresAt < Date.now()) {
|
|
134
|
+
store.delete(key);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
return hit.value;
|
|
138
|
+
},
|
|
139
|
+
async set(key, value, ttlMs) {
|
|
140
|
+
store.set(key, {
|
|
141
|
+
value,
|
|
142
|
+
expiresAt: ttlMs && ttlMs > 0 ? Date.now() + ttlMs : 0,
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** A cache that never stores anything. Useful for tests that assert fetch counts. */
|
|
148
|
+
function noCache() {
|
|
149
|
+
return {
|
|
150
|
+
async get() { return undefined; },
|
|
151
|
+
async set() { },
|
|
152
|
+
};
|
|
153
|
+
}
|