@cloak.dev/sdk 0.2.1 → 0.2.2-staging.0f03668
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -11
- package/dist/index.cjs +378 -31
- package/dist/index.d.cts +160 -1
- package/dist/index.d.ts +160 -1
- package/dist/index.js +372 -31
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -624,12 +624,14 @@ __export(index_exports, {
|
|
|
624
624
|
createCloakError: () => createCloakError,
|
|
625
625
|
createDepositInstruction: () => createDepositInstruction,
|
|
626
626
|
createLogger: () => createLogger,
|
|
627
|
+
createRecoverableChangeUtxo: () => createRecoverableChangeUtxo,
|
|
627
628
|
createRecoverableDepositUtxo: () => createRecoverableDepositUtxo,
|
|
628
629
|
createUtxo: () => createUtxo,
|
|
629
630
|
createZeroUtxo: () => createZeroUtxo,
|
|
630
631
|
decryptCompactChainNote: () => decryptCompactChainNote,
|
|
631
632
|
decryptComplianceMetadataWithMasterKey: () => decryptComplianceMetadataWithMasterKey,
|
|
632
633
|
decryptTransactionMetadata: () => decryptTransactionMetadata,
|
|
634
|
+
deriveChangeNoteBlinding: () => deriveChangeNoteBlinding,
|
|
633
635
|
deriveDepositNoteSecrets: () => deriveDepositNoteSecrets,
|
|
634
636
|
deriveDiversifiedViewingKey: () => deriveDiversifiedViewingKey,
|
|
635
637
|
deriveDiversifier: () => deriveDiversifier,
|
|
@@ -715,6 +717,7 @@ __export(index_exports, {
|
|
|
715
717
|
loadPendingDeposits: () => loadPendingDeposits,
|
|
716
718
|
loadPendingWithdrawals: () => loadPendingWithdrawals,
|
|
717
719
|
loadVerifiedCircuitArtifacts: () => loadVerifiedCircuitArtifacts,
|
|
720
|
+
matchChangeNote: () => matchChangeNote,
|
|
718
721
|
matchDepositNote: () => matchDepositNote,
|
|
719
722
|
matchSwapRefundLeaf: () => matchSwapRefundLeaf,
|
|
720
723
|
openRecipientDeliveryNote: () => openRecipientDeliveryNote,
|
|
@@ -735,6 +738,7 @@ __export(index_exports, {
|
|
|
735
738
|
pubkeyToFieldElement: () => pubkeyToFieldElement,
|
|
736
739
|
pubkeyToLimbs: () => pubkeyToLimbs,
|
|
737
740
|
randomBytes: () => randomBytes,
|
|
741
|
+
randomChangeNoteSalt: () => randomChangeNoteSalt,
|
|
738
742
|
randomDepositNoteSalt: () => randomDepositNoteSalt,
|
|
739
743
|
randomFieldElement: () => randomFieldElement,
|
|
740
744
|
readMerkleTreeState: () => readMerkleTreeState,
|
|
@@ -1387,7 +1391,7 @@ function parseStrictViewingKeyChallenge(response, userPubkey, viewingKeyHex) {
|
|
|
1387
1391
|
|
|
1388
1392
|
// src/config/relay.ts
|
|
1389
1393
|
var CLOAK_PRODUCTION_RELAY_URL = "https://api.cloak.ag";
|
|
1390
|
-
var RELAY_ORIGIN_ALLOWLIST = [
|
|
1394
|
+
var RELAY_ORIGIN_ALLOWLIST = ["https://staging-api.cloak.ag"];
|
|
1391
1395
|
var ABSOLUTE_URL = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
1392
1396
|
var LOOPBACK_IPV4 = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
1393
1397
|
var THIS_NETWORK_IPV4 = /^0\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
@@ -5294,6 +5298,93 @@ async function matchDepositNote(params) {
|
|
|
5294
5298
|
return { ...secrets, amount, mintAddress, commitment: candidate, noteSalt };
|
|
5295
5299
|
}
|
|
5296
5300
|
|
|
5301
|
+
// src/notes/change-note.ts
|
|
5302
|
+
var import_blake36 = require("@noble/hashes/blake3");
|
|
5303
|
+
init_utxo();
|
|
5304
|
+
init_inputs();
|
|
5305
|
+
var CHANGE_NOTE_DOMAIN = new TextEncoder().encode("cloak_change_note_v1");
|
|
5306
|
+
var CHANGE_BLINDING_INFO = new TextEncoder().encode("blinding");
|
|
5307
|
+
var MAX_OUTPUT_INDEX = 1;
|
|
5308
|
+
var MAX_CHAIN_NOTE_SALT2 = (1n << BigInt(CHAIN_NOTE_SALT_BITS)) - 1n;
|
|
5309
|
+
function saltToBytes2(noteSalt) {
|
|
5310
|
+
if (typeof noteSalt !== "bigint" || noteSalt <= 0n || noteSalt > MAX_CHAIN_NOTE_SALT2) {
|
|
5311
|
+
throw new Error(`noteSalt must be a positive ${CHAIN_NOTE_SALT_BITS}-bit value`);
|
|
5312
|
+
}
|
|
5313
|
+
const out = new Uint8Array(32);
|
|
5314
|
+
let v = noteSalt;
|
|
5315
|
+
for (let i = 31; i >= 0; i--) {
|
|
5316
|
+
out[i] = Number(v & 0xffn);
|
|
5317
|
+
v >>= 8n;
|
|
5318
|
+
}
|
|
5319
|
+
return out;
|
|
5320
|
+
}
|
|
5321
|
+
function toFieldSecret3(bytes) {
|
|
5322
|
+
let value = 0n;
|
|
5323
|
+
for (let i = 0; i < 32; i++) value = value << 8n | BigInt(bytes[i]);
|
|
5324
|
+
const reduced = value % (BN254_MODULUS >> 4n);
|
|
5325
|
+
return reduced === 0n ? 1n : reduced;
|
|
5326
|
+
}
|
|
5327
|
+
function randomChangeNoteSalt() {
|
|
5328
|
+
const bytes = randomBytes(12);
|
|
5329
|
+
let v = 0n;
|
|
5330
|
+
for (const b of bytes) v = v << 8n | BigInt(b);
|
|
5331
|
+
return v === 0n ? 1n : v;
|
|
5332
|
+
}
|
|
5333
|
+
function deriveChangeNoteBlinding(viewingKeyNk, noteSalt, outputIndex) {
|
|
5334
|
+
if (!viewingKeyNk || !(viewingKeyNk instanceof Uint8Array) || viewingKeyNk.length !== 32) {
|
|
5335
|
+
throw new Error("viewingKeyNk must be 32 bytes");
|
|
5336
|
+
}
|
|
5337
|
+
if (!Number.isInteger(outputIndex) || outputIndex < 0 || outputIndex > MAX_OUTPUT_INDEX) {
|
|
5338
|
+
throw new Error(`outputIndex must be 0..${MAX_OUTPUT_INDEX}`);
|
|
5339
|
+
}
|
|
5340
|
+
const salt = saltToBytes2(noteSalt);
|
|
5341
|
+
const preimage = new Uint8Array(
|
|
5342
|
+
CHANGE_NOTE_DOMAIN.length + viewingKeyNk.length + salt.length + 1 + CHANGE_BLINDING_INFO.length
|
|
5343
|
+
);
|
|
5344
|
+
let off = 0;
|
|
5345
|
+
preimage.set(CHANGE_NOTE_DOMAIN, off);
|
|
5346
|
+
off += CHANGE_NOTE_DOMAIN.length;
|
|
5347
|
+
preimage.set(viewingKeyNk, off);
|
|
5348
|
+
off += viewingKeyNk.length;
|
|
5349
|
+
preimage.set(salt, off);
|
|
5350
|
+
off += salt.length;
|
|
5351
|
+
preimage[off] = outputIndex;
|
|
5352
|
+
off += 1;
|
|
5353
|
+
preimage.set(CHANGE_BLINDING_INFO, off);
|
|
5354
|
+
return toFieldSecret3((0, import_blake36.blake3)(preimage));
|
|
5355
|
+
}
|
|
5356
|
+
async function createRecoverableChangeUtxo(amount, keypair, viewingKeyNk, mintAddress = NATIVE_SOL_MINT, noteSalt = randomChangeNoteSalt(), outputIndex = 0) {
|
|
5357
|
+
if (typeof amount !== "bigint" || amount <= 0n) {
|
|
5358
|
+
throw new Error("amount must be a positive bigint");
|
|
5359
|
+
}
|
|
5360
|
+
const blinding = deriveChangeNoteBlinding(viewingKeyNk, noteSalt, outputIndex);
|
|
5361
|
+
const utxo = { amount, keypair, blinding, mintAddress };
|
|
5362
|
+
utxo.commitment = await computeCommitment2(utxo);
|
|
5363
|
+
return { utxo, noteSalt };
|
|
5364
|
+
}
|
|
5365
|
+
function normalizeCommitment2(value) {
|
|
5366
|
+
if (typeof value === "bigint") return value;
|
|
5367
|
+
if (typeof value !== "string") return null;
|
|
5368
|
+
const clean = value.startsWith("0x") ? value.slice(2) : value;
|
|
5369
|
+
if (!/^[0-9a-fA-F]{1,64}$/.test(clean)) return null;
|
|
5370
|
+
return BigInt("0x" + clean);
|
|
5371
|
+
}
|
|
5372
|
+
async function matchChangeNote(params) {
|
|
5373
|
+
const { viewingKeyNk, noteSalt, amount, keypair, mintAddress, outputIndex, outputCommitments } = params;
|
|
5374
|
+
if (typeof amount !== "bigint" || amount <= 0n) return null;
|
|
5375
|
+
if (!keypair || typeof keypair.publicKey !== "bigint" || keypair.publicKey === 0n) return null;
|
|
5376
|
+
let blinding;
|
|
5377
|
+
try {
|
|
5378
|
+
blinding = deriveChangeNoteBlinding(viewingKeyNk, noteSalt, outputIndex);
|
|
5379
|
+
} catch {
|
|
5380
|
+
return null;
|
|
5381
|
+
}
|
|
5382
|
+
const candidate = await computeCommitment2({ amount, keypair, blinding, mintAddress });
|
|
5383
|
+
const published = (outputCommitments ?? []).map(normalizeCommitment2).filter((value) => value !== null);
|
|
5384
|
+
if (!published.some((value) => value === candidate)) return null;
|
|
5385
|
+
return { keypair, blinding, amount, mintAddress, commitment: candidate, noteSalt };
|
|
5386
|
+
}
|
|
5387
|
+
|
|
5297
5388
|
// src/flows/transact.ts
|
|
5298
5389
|
var import_circomlibjs4 = require("circomlibjs");
|
|
5299
5390
|
var import_tweetnacl6 = __toESM(require("tweetnacl"), 1);
|
|
@@ -5879,6 +5970,84 @@ async function fetchAltAddressesFromRelayHealth(relayUrl) {
|
|
|
5879
5970
|
return [];
|
|
5880
5971
|
}
|
|
5881
5972
|
}
|
|
5973
|
+
async function fetchSupplementalAltFromRelay(relayUrl, params) {
|
|
5974
|
+
const body = JSON.stringify({
|
|
5975
|
+
mint: params.mint.toBase58(),
|
|
5976
|
+
nullifiers: [
|
|
5977
|
+
Buffer.from(params.nullifiers[0]).toString("hex"),
|
|
5978
|
+
Buffer.from(params.nullifiers[1]).toString("hex")
|
|
5979
|
+
],
|
|
5980
|
+
bind0: Buffer.from(params.bind0).toString("hex"),
|
|
5981
|
+
depositor: params.depositor.toBase58()
|
|
5982
|
+
});
|
|
5983
|
+
let response;
|
|
5984
|
+
try {
|
|
5985
|
+
response = await relayFetch(`${relayUrl.replace(/\/$/, "")}/supplemental-alt`, {
|
|
5986
|
+
method: "POST",
|
|
5987
|
+
headers: { "Content-Type": "application/json" },
|
|
5988
|
+
body
|
|
5989
|
+
});
|
|
5990
|
+
} catch (err) {
|
|
5991
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5992
|
+
throw new Error(`Supplemental ALT request to the relay failed: ${msg}`);
|
|
5993
|
+
}
|
|
5994
|
+
if (!response.ok) {
|
|
5995
|
+
let text = "";
|
|
5996
|
+
try {
|
|
5997
|
+
text = await response.text();
|
|
5998
|
+
} catch {
|
|
5999
|
+
}
|
|
6000
|
+
throw new Error(
|
|
6001
|
+
`Supplemental ALT request failed (${response.status})${text ? `: ${text}` : ""}`
|
|
6002
|
+
);
|
|
6003
|
+
}
|
|
6004
|
+
let json;
|
|
6005
|
+
try {
|
|
6006
|
+
json = await response.json();
|
|
6007
|
+
} catch {
|
|
6008
|
+
throw new Error("Supplemental ALT response was not valid JSON");
|
|
6009
|
+
}
|
|
6010
|
+
const table = json?.table;
|
|
6011
|
+
if (typeof table !== "string" || table.length === 0) {
|
|
6012
|
+
throw new Error("Supplemental ALT response is missing a 'table' address");
|
|
6013
|
+
}
|
|
6014
|
+
try {
|
|
6015
|
+
return new import_web39.PublicKey(table);
|
|
6016
|
+
} catch {
|
|
6017
|
+
throw new Error(`Supplemental ALT response 'table' is not a valid public key: ${table}`);
|
|
6018
|
+
}
|
|
6019
|
+
}
|
|
6020
|
+
async function resolveRelaySupplementalAlt(connection, table, expected, pollOpts) {
|
|
6021
|
+
const pollIntervalMs = pollOpts?.pollIntervalMs ?? 150;
|
|
6022
|
+
const timeoutMs = pollOpts?.timeoutMs ?? 5e3;
|
|
6023
|
+
const expectedB58 = expected.map((pk) => pk.toBase58());
|
|
6024
|
+
const deadline = Date.now() + timeoutMs;
|
|
6025
|
+
for (; ; ) {
|
|
6026
|
+
const result = await connection.getAddressLookupTable(table, { commitment: "confirmed" });
|
|
6027
|
+
if (!result.value) {
|
|
6028
|
+
throw new Error(`Supplemental ALT ${table.toBase58()} could not be fetched from the RPC.`);
|
|
6029
|
+
}
|
|
6030
|
+
const account = result.value;
|
|
6031
|
+
const present = new Set(account.state.addresses.map((a) => a.toBase58()));
|
|
6032
|
+
const missing = expectedB58.filter((addr) => !present.has(addr));
|
|
6033
|
+
if (missing.length === 0) {
|
|
6034
|
+
const currentSlot = await connection.getSlot("confirmed");
|
|
6035
|
+
if (account.state.lastExtendedSlot < currentSlot) {
|
|
6036
|
+
return account;
|
|
6037
|
+
}
|
|
6038
|
+
if (Date.now() >= deadline) {
|
|
6039
|
+
throw new Error(
|
|
6040
|
+
`Supplemental ALT ${table.toBase58()} did not become resolvable within ${timeoutMs}ms (lastExtendedSlot=${account.state.lastExtendedSlot} never fell behind current slot=${currentSlot}).`
|
|
6041
|
+
);
|
|
6042
|
+
}
|
|
6043
|
+
} else if (Date.now() >= deadline) {
|
|
6044
|
+
throw new Error(
|
|
6045
|
+
`Supplemental ALT ${table.toBase58()} is still missing expected address(es) after ${timeoutMs}ms: ` + missing.join(", ")
|
|
6046
|
+
);
|
|
6047
|
+
}
|
|
6048
|
+
await sleep2(pollIntervalMs);
|
|
6049
|
+
}
|
|
6050
|
+
}
|
|
5882
6051
|
function deriveRelayUrlFromRiskQuoteUrl(riskQuoteUrl) {
|
|
5883
6052
|
if (!riskQuoteUrl) return void 0;
|
|
5884
6053
|
const trimmed = riskQuoteUrl.replace(/\/$/, "");
|
|
@@ -6549,7 +6718,7 @@ async function planDirectV0Submission(args) {
|
|
|
6549
6718
|
);
|
|
6550
6719
|
return { tier: "minimal", instructions: minimal, supplementalAltRequested, fullSize, minimalSize };
|
|
6551
6720
|
}
|
|
6552
|
-
async function submitViaExternalFeePayer(connection, depositor, externalFeePayer, externalFeePayerPubkey, instructions, addressLookupTableAccounts, onProgress, allowSupplementalAlt = true) {
|
|
6721
|
+
async function submitViaExternalFeePayer(connection, depositor, externalFeePayer, externalFeePayerPubkey, instructions, addressLookupTableAccounts, onProgress, allowSupplementalAlt = true, relayAltAttempt) {
|
|
6553
6722
|
if (!depositor.signTransaction) {
|
|
6554
6723
|
throw new Error(
|
|
6555
6724
|
"externalFeePayer requires wallet-style signTransaction \u2014 keypair-only depositors aren't supported for external fee payment."
|
|
@@ -6578,6 +6747,18 @@ async function submitViaExternalFeePayer(connection, depositor, externalFeePayer
|
|
|
6578
6747
|
};
|
|
6579
6748
|
const compressWithSupplementalAlt = async (instrs, extraAddresses = []) => {
|
|
6580
6749
|
onProgress?.("Transaction exceeds packet limit; creating supplemental ALT...");
|
|
6750
|
+
if (relayAltAttempt) {
|
|
6751
|
+
try {
|
|
6752
|
+
onProgress?.("Requesting supplemental lookup table from relay...");
|
|
6753
|
+
addressLookupTableAccounts = [await relayAltAttempt()];
|
|
6754
|
+
return;
|
|
6755
|
+
} catch (err) {
|
|
6756
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6757
|
+
onProgress?.(
|
|
6758
|
+
`Relay supplemental ALT failed (${msg}); falling back to a depositor-signed table.`
|
|
6759
|
+
);
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6581
6762
|
try {
|
|
6582
6763
|
const supplementalAddresses = dedupePubkeys([
|
|
6583
6764
|
...collectLookupCandidatesFromInstructions(instrs, externalFeePayerPubkey, void 0),
|
|
@@ -6645,7 +6826,7 @@ async function submitViaExternalFeePayer(connection, depositor, externalFeePayer
|
|
|
6645
6826
|
}
|
|
6646
6827
|
return signature;
|
|
6647
6828
|
}
|
|
6648
|
-
async function submitTransactionDirect(connection, programId, depositor, proofBytes, publicInputsBytes, nullifiers, mint, recipient, riskOracleQueue, riskQuoteUrl, getRiskQuoteInstruction, onProgress, addressLookupTableAccounts, rangeApiKey, encryptedNoteBytes, relayUrl, altAddresses, relayer, relayerFee, onTransactProofBuilt, externalFeePayer) {
|
|
6829
|
+
async function submitTransactionDirect(connection, programId, depositor, proofBytes, publicInputsBytes, nullifiers, mint, recipient, riskOracleQueue, riskQuoteUrl, getRiskQuoteInstruction, onProgress, addressLookupTableAccounts, rangeApiKey, encryptedNoteBytes, relayUrl, altAddresses, relayer, relayerFee, onTransactProofBuilt, externalFeePayer, relaySupplementalAlt) {
|
|
6649
6830
|
onProgress?.("Building transaction...");
|
|
6650
6831
|
addressLookupTableAccounts = await resolveAddressLookupTableAccounts(
|
|
6651
6832
|
connection,
|
|
@@ -6666,14 +6847,8 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6666
6847
|
"rangeApiKey direct risk quotes do not support H-01 deposit nonce binding. Use relayUrl/riskQuoteUrl or getRiskQuoteInstruction."
|
|
6667
6848
|
);
|
|
6668
6849
|
}
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress, [], externalFeePayer);
|
|
6672
|
-
}
|
|
6673
|
-
if (isDeposit && isSplPool && (!addressLookupTableAccounts || addressLookupTableAccounts.length === 0)) {
|
|
6674
|
-
onProgress?.("Creating address lookup table (SPL deposit requires v0 tx)...");
|
|
6675
|
-
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress, [], externalFeePayer);
|
|
6676
|
-
}
|
|
6850
|
+
const needsAltForChainNotes = isDeposit && Boolean(encryptedNoteBytes && encryptedNoteBytes.length > 0);
|
|
6851
|
+
const needsAltForSplDeposit = isDeposit && isSplPool;
|
|
6677
6852
|
const publicAmountBytes = publicInputsBytes.slice(32, 40);
|
|
6678
6853
|
const publicAmountBuffer = Buffer.from(publicAmountBytes);
|
|
6679
6854
|
const publicAmount = readBigInt64LE(publicAmountBuffer, 0);
|
|
@@ -6725,6 +6900,49 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6725
6900
|
const nullifier1Hex = Buffer.from(nullifiers[1]).toString("hex");
|
|
6726
6901
|
let riskNoncePda;
|
|
6727
6902
|
let depositNonce = null;
|
|
6903
|
+
let relaySupplementalAltPromise;
|
|
6904
|
+
const requestRelaySupplementalAlt = () => {
|
|
6905
|
+
const [nullifierPda0] = deriveNullifierPDA(programId, pdas.pool, nullifiers[0]);
|
|
6906
|
+
const [nullifierPda1] = deriveNullifierPDA(programId, pdas.pool, nullifiers[1]);
|
|
6907
|
+
const [riskNoncePdaForAlt] = deriveRiskNoncePDA(programId, depositNonce);
|
|
6908
|
+
const depositorAta = (0, import_spl_token.getAssociatedTokenAddressSync)(mint, depositor.publicKey, false, import_spl_token.TOKEN_PROGRAM_ID);
|
|
6909
|
+
return fetchSupplementalAltFromRelay(relayUrl, {
|
|
6910
|
+
mint,
|
|
6911
|
+
nullifiers,
|
|
6912
|
+
bind0: depositNonce,
|
|
6913
|
+
depositor: depositor.publicKey
|
|
6914
|
+
}).then(
|
|
6915
|
+
(table) => resolveRelaySupplementalAlt(connection, table, [
|
|
6916
|
+
nullifierPda0,
|
|
6917
|
+
nullifierPda1,
|
|
6918
|
+
riskNoncePdaForAlt,
|
|
6919
|
+
depositorAta
|
|
6920
|
+
])
|
|
6921
|
+
);
|
|
6922
|
+
};
|
|
6923
|
+
const relayAltEligible = () => Boolean(relaySupplementalAlt && relayUrl && isDeposit && isSplPool && depositNonce && nullifiers);
|
|
6924
|
+
const getRelaySupplementalAlt = () => {
|
|
6925
|
+
if (!relaySupplementalAltPromise) {
|
|
6926
|
+
relaySupplementalAltPromise = requestRelaySupplementalAlt();
|
|
6927
|
+
}
|
|
6928
|
+
return relaySupplementalAltPromise;
|
|
6929
|
+
};
|
|
6930
|
+
const acquireDepositAlt = async () => {
|
|
6931
|
+
if (relayAltEligible()) {
|
|
6932
|
+
try {
|
|
6933
|
+
onProgress?.("Requesting lookup table from relay...");
|
|
6934
|
+
const relayAlt = await getRelaySupplementalAlt();
|
|
6935
|
+
return [relayAlt];
|
|
6936
|
+
} catch (err) {
|
|
6937
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6938
|
+
onProgress?.(
|
|
6939
|
+
`Relay lookup table failed (${msg}); falling back to a depositor-signed table.`
|
|
6940
|
+
);
|
|
6941
|
+
}
|
|
6942
|
+
}
|
|
6943
|
+
onProgress?.("Creating address lookup table for V0 transaction...");
|
|
6944
|
+
return createEphemeralALT(connection, depositor, onProgress, [], externalFeePayer);
|
|
6945
|
+
};
|
|
6728
6946
|
if ((isDeposit || isSend) && riskCheckEnabled && !riskQuoteIx) {
|
|
6729
6947
|
if (getRiskQuoteInstruction) {
|
|
6730
6948
|
onProgress?.("Fetching risk quote (custom)...");
|
|
@@ -6755,10 +6973,13 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6755
6973
|
}
|
|
6756
6974
|
if (depositNonce) {
|
|
6757
6975
|
[riskNoncePda] = deriveRiskNoncePDA(programId, depositNonce);
|
|
6976
|
+
if (relaySupplementalAlt && relayUrl && isSplPool) {
|
|
6977
|
+
getRelaySupplementalAlt().catch(() => {
|
|
6978
|
+
});
|
|
6979
|
+
}
|
|
6758
6980
|
}
|
|
6759
|
-
if (
|
|
6760
|
-
|
|
6761
|
-
addressLookupTableAccounts = await createEphemeralALT(connection, depositor, onProgress, [], externalFeePayer);
|
|
6981
|
+
if ((!addressLookupTableAccounts || addressLookupTableAccounts.length === 0) && (riskQuoteIx || needsAltForChainNotes || needsAltForSplDeposit)) {
|
|
6982
|
+
addressLookupTableAccounts = await acquireDepositAlt();
|
|
6762
6983
|
}
|
|
6763
6984
|
}
|
|
6764
6985
|
if (!isDeposit && riskCheckEnabled && recipient && riskQuoteUrl && !riskQuoteIx) {
|
|
@@ -6824,7 +7045,14 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6824
7045
|
externalFeePayerPubkey,
|
|
6825
7046
|
fullInstructions,
|
|
6826
7047
|
addressLookupTableAccounts,
|
|
6827
|
-
onProgress
|
|
7048
|
+
onProgress,
|
|
7049
|
+
void 0,
|
|
7050
|
+
// `addressLookupTableAccounts` above already carries the relay-owned table when eligible
|
|
7051
|
+
// (acquireDepositAlt ran before this branch, same as the non-externalFeePayer path). This is
|
|
7052
|
+
// only for submitViaExternalFeePayer's OWN, separate supplemental round — triggered by the
|
|
7053
|
+
// external payer's extra signature and payment-instruction accounts pushing an already-ALT'd
|
|
7054
|
+
// tx back over the limit — so that round also tries the relay before an ephemeral fallback.
|
|
7055
|
+
relayAltEligible() ? getRelaySupplementalAlt : void 0
|
|
6828
7056
|
);
|
|
6829
7057
|
} else if (useV0) {
|
|
6830
7058
|
const plan = await planDirectV0Submission({
|
|
@@ -6833,6 +7061,23 @@ async function submitTransactionDirect(connection, programId, depositor, proofBy
|
|
|
6833
7061
|
compact: compactInstructions,
|
|
6834
7062
|
minimal: minimalInstructions,
|
|
6835
7063
|
createSupplementalAlt: async () => {
|
|
7064
|
+
if (relayAltEligible()) {
|
|
7065
|
+
try {
|
|
7066
|
+
onProgress?.("Requesting supplemental lookup table from relay...");
|
|
7067
|
+
const relayAlt = await getRelaySupplementalAlt();
|
|
7068
|
+
addressLookupTableAccounts = [
|
|
7069
|
+
...(addressLookupTableAccounts ?? []).filter((t) => !t.key.equals(relayAlt.key)),
|
|
7070
|
+
relayAlt
|
|
7071
|
+
];
|
|
7072
|
+
({ blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash());
|
|
7073
|
+
return;
|
|
7074
|
+
} catch (err) {
|
|
7075
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7076
|
+
onProgress?.(
|
|
7077
|
+
`Relay supplemental ALT failed (${msg}); falling back to a depositor-signed table.`
|
|
7078
|
+
);
|
|
7079
|
+
}
|
|
7080
|
+
}
|
|
6836
7081
|
const supplementalAddresses = collectLookupCandidatesFromInstructions(
|
|
6837
7082
|
minimalInstructions,
|
|
6838
7083
|
depositor.publicKey,
|
|
@@ -7625,6 +7870,21 @@ async function transact(params, options) {
|
|
|
7625
7870
|
"options.chainNoteSalt requires an explicit chainNoteViewingKeyNk (or getChainNoteViewingKeyNk). The salt anchors a deposit note derived from that nk; inferring nk from the output note's own key would encrypt the chain note under a different key than the note was derived from, and the deposit would be undiscoverable."
|
|
7626
7871
|
);
|
|
7627
7872
|
}
|
|
7873
|
+
const chainNoteSalt = options.chainNoteSalt !== void 0 ? assertChainNoteSalt(options.chainNoteSalt) : randomChainNoteSalt();
|
|
7874
|
+
const chainNoteWillCarrySalt = !options.disableChainNotes && !(options.encryptedNotes && options.encryptedNotes.length > 0);
|
|
7875
|
+
if (explicitChainNoteNk && chainNoteWillCarrySalt) {
|
|
7876
|
+
const inputOwners = new Set(inputUtxos.map((u) => u.keypair.publicKey));
|
|
7877
|
+
for (let i = 0; i < outputUtxos.length; i++) {
|
|
7878
|
+
const out = outputUtxos[i];
|
|
7879
|
+
if (!out || out.amount <= BigInt(0)) continue;
|
|
7880
|
+
if (!inputOwners.has(out.keypair.publicKey)) continue;
|
|
7881
|
+
if (out.blinding !== deriveChangeNoteBlinding(explicitChainNoteNk, chainNoteSalt, i)) {
|
|
7882
|
+
throw new Error(
|
|
7883
|
+
`Output ${i} is change (amount ${out.amount}, owned by an input's keypair) but its blinding is not the one derivable from this wallet's viewing key. It was almost certainly built with \`createUtxo\`, whose blinding is random and is written nowhere on chain \u2014 if the caller ever drops the returned note, the funds are unspendable forever. Build change with \`createRecoverableChangeUtxo(amount, keypair, nk, mint, salt, outputIndex)\` and pass the same salt as \`options.chainNoteSalt\`, or use \`partialWithdraw\` / \`transfer\` / \`swapWithChange\`, which do it for you.`
|
|
7884
|
+
);
|
|
7885
|
+
}
|
|
7886
|
+
}
|
|
7887
|
+
}
|
|
7628
7888
|
assertAllowedRpcConnection(connection);
|
|
7629
7889
|
await ensureViewingKeyRegistered(options, onProgress, fallbackNk);
|
|
7630
7890
|
const resolvedChainNoteNk = explicitChainNoteNk ?? fallbackNk ?? null;
|
|
@@ -7979,7 +8239,6 @@ async function transact(params, options) {
|
|
|
7979
8239
|
const maxFee = isWithdrawal ? protocolFeeSnapshot : BigInt(0);
|
|
7980
8240
|
const extDataHash = await computeExtDataHash(recipient ?? null, relayerFee, relayer ?? null, maxFee);
|
|
7981
8241
|
const chainNoteTimestamp = BigInt(Date.now());
|
|
7982
|
-
const chainNoteSalt = options.chainNoteSalt !== void 0 ? assertChainNoteSalt(options.chainNoteSalt) : randomChainNoteSalt();
|
|
7983
8242
|
const mintField = pubkeyToFieldElement(mint);
|
|
7984
8243
|
let signature = "pending-" + Date.now().toString();
|
|
7985
8244
|
let commitmentIndices = [-1, -1];
|
|
@@ -8254,7 +8513,8 @@ async function transact(params, options) {
|
|
|
8254
8513
|
relayer ?? null,
|
|
8255
8514
|
relayerFee,
|
|
8256
8515
|
options.onTransactProofBuilt,
|
|
8257
|
-
externalFeePayer
|
|
8516
|
+
externalFeePayer,
|
|
8517
|
+
options.relaySupplementalAlt
|
|
8258
8518
|
);
|
|
8259
8519
|
signature = directResult.signature;
|
|
8260
8520
|
commitmentIndices = directResult.commitmentIndices;
|
|
@@ -8646,16 +8906,30 @@ async function transfer(inputUtxos, recipientPubkey, amount, options) {
|
|
|
8646
8906
|
const change = inputSum - amount;
|
|
8647
8907
|
const myKeypair = inputUtxos[0].keypair;
|
|
8648
8908
|
const mint = inputUtxos[0].mintAddress;
|
|
8909
|
+
const transferNk = await resolveChainNoteNk(options);
|
|
8910
|
+
const changeNoteSalt = transferNk ? randomChangeNoteSalt() : void 0;
|
|
8911
|
+
const isSendToSelf = inputUtxos.some((u) => u.keypair.publicKey === recipientPubkey);
|
|
8649
8912
|
const recipientKeypair = {
|
|
8650
8913
|
privateKey: BigInt(0),
|
|
8651
8914
|
// Recipient's private key unknown
|
|
8652
8915
|
publicKey: recipientPubkey
|
|
8653
8916
|
};
|
|
8654
|
-
const recipientUtxo = await createUtxo(amount, recipientKeypair, mint);
|
|
8917
|
+
const recipientUtxo = transferNk && isSendToSelf ? (await createRecoverableChangeUtxo(amount, myKeypair, transferNk, mint, changeNoteSalt, 0)).utxo : await createUtxo(amount, recipientKeypair, mint);
|
|
8655
8918
|
const outputUtxos = [recipientUtxo];
|
|
8656
8919
|
if (change > BigInt(0)) {
|
|
8657
|
-
|
|
8658
|
-
|
|
8920
|
+
if (transferNk) {
|
|
8921
|
+
const { utxo } = await createRecoverableChangeUtxo(
|
|
8922
|
+
change,
|
|
8923
|
+
myKeypair,
|
|
8924
|
+
transferNk,
|
|
8925
|
+
mint,
|
|
8926
|
+
changeNoteSalt,
|
|
8927
|
+
1
|
|
8928
|
+
);
|
|
8929
|
+
outputUtxos.push(utxo);
|
|
8930
|
+
} else {
|
|
8931
|
+
outputUtxos.push(await createUtxo(change, myKeypair, mint));
|
|
8932
|
+
}
|
|
8659
8933
|
}
|
|
8660
8934
|
return transact(
|
|
8661
8935
|
{
|
|
@@ -8664,7 +8938,7 @@ async function transfer(inputUtxos, recipientPubkey, amount, options) {
|
|
|
8664
8938
|
externalAmount: BigInt(0)
|
|
8665
8939
|
// Pure shield-to-shield
|
|
8666
8940
|
},
|
|
8667
|
-
options
|
|
8941
|
+
changeNoteSalt !== void 0 ? { ...options, chainNoteSalt: changeNoteSalt } : options
|
|
8668
8942
|
);
|
|
8669
8943
|
}
|
|
8670
8944
|
async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
@@ -8681,7 +8955,9 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
8681
8955
|
utxos.sort((a, b) => a.amount > b.amount ? 1 : a.amount < b.amount ? -1 : 0);
|
|
8682
8956
|
const [small1, small2, ...rest] = utxos;
|
|
8683
8957
|
const mergedAmount = small1.amount + small2.amount;
|
|
8684
|
-
const
|
|
8958
|
+
const mergeNk = await resolveChainNoteNk(options);
|
|
8959
|
+
const mergeSalt = mergeNk ? randomChangeNoteSalt() : void 0;
|
|
8960
|
+
const mergedOutput = mergeNk ? (await createRecoverableChangeUtxo(mergedAmount, myKeypair, mergeNk, mint, mergeSalt, 0)).utxo : await createUtxo(mergedAmount, myKeypair, mint);
|
|
8685
8961
|
const mergeResult = await transact(
|
|
8686
8962
|
{
|
|
8687
8963
|
inputUtxos: [small1, small2],
|
|
@@ -8691,7 +8967,8 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
8691
8967
|
},
|
|
8692
8968
|
{
|
|
8693
8969
|
...options,
|
|
8694
|
-
cachedMerkleTree: cachedTree
|
|
8970
|
+
cachedMerkleTree: cachedTree,
|
|
8971
|
+
...mergeSalt !== void 0 && { chainNoteSalt: mergeSalt }
|
|
8695
8972
|
}
|
|
8696
8973
|
);
|
|
8697
8974
|
cachedTree = mergeResult.merkleTree;
|
|
@@ -8704,9 +8981,25 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
8704
8981
|
const finalInputSum = sumUtxoAmounts(utxos);
|
|
8705
8982
|
const change = finalInputSum - withdrawAmount;
|
|
8706
8983
|
const outputUtxos = [];
|
|
8984
|
+
let changeNoteSalt;
|
|
8707
8985
|
if (change > BigInt(0)) {
|
|
8708
|
-
const
|
|
8709
|
-
|
|
8986
|
+
const changeNk = await resolveChainNoteNk(options);
|
|
8987
|
+
if (changeNk) {
|
|
8988
|
+
const salt = randomChangeNoteSalt();
|
|
8989
|
+
const { utxo } = await createRecoverableChangeUtxo(
|
|
8990
|
+
change,
|
|
8991
|
+
myKeypair,
|
|
8992
|
+
changeNk,
|
|
8993
|
+
mint,
|
|
8994
|
+
salt,
|
|
8995
|
+
0
|
|
8996
|
+
// partialWithdraw puts change at output 0
|
|
8997
|
+
);
|
|
8998
|
+
outputUtxos.push(utxo);
|
|
8999
|
+
changeNoteSalt = salt;
|
|
9000
|
+
} else {
|
|
9001
|
+
outputUtxos.push(await createUtxo(change, myKeypair, mint));
|
|
9002
|
+
}
|
|
8710
9003
|
}
|
|
8711
9004
|
return transact(
|
|
8712
9005
|
{
|
|
@@ -8717,7 +9010,8 @@ async function partialWithdraw(inputUtxos, recipient, withdrawAmount, options) {
|
|
|
8717
9010
|
},
|
|
8718
9011
|
{
|
|
8719
9012
|
...options,
|
|
8720
|
-
cachedMerkleTree: cachedTree
|
|
9013
|
+
cachedMerkleTree: cachedTree,
|
|
9014
|
+
...changeNoteSalt !== void 0 && { chainNoteSalt: changeNoteSalt }
|
|
8721
9015
|
}
|
|
8722
9016
|
);
|
|
8723
9017
|
}
|
|
@@ -8851,7 +9145,16 @@ async function swapUtxo(params, options) {
|
|
|
8851
9145
|
onProgress?.("Validating transaction parameters...");
|
|
8852
9146
|
const swapFallbackNk = getNkFromUtxoPrivateKey(inputUtxos[0].keypair.privateKey);
|
|
8853
9147
|
await ensureViewingKeyRegistered(options, onProgress, swapFallbackNk);
|
|
8854
|
-
const
|
|
9148
|
+
const explicitSwapChainNoteNk = await resolveChainNoteNk(options);
|
|
9149
|
+
const resolvedSwapChainNoteNk = explicitSwapChainNoteNk ?? swapFallbackNk;
|
|
9150
|
+
const chainNoteSalt = options.chainNoteSalt !== void 0 ? assertChainNoteSalt(options.chainNoteSalt) : randomChainNoteSalt();
|
|
9151
|
+
if (explicitSwapChainNoteNk && changeUtxo && changeUtxo.amount > BigInt(0) && inputUtxos.some((u) => u.keypair.publicKey === changeUtxo.keypair.publicKey)) {
|
|
9152
|
+
if (changeUtxo.blinding !== deriveChangeNoteBlinding(explicitSwapChainNoteNk, chainNoteSalt, 0)) {
|
|
9153
|
+
throw new Error(
|
|
9154
|
+
`Swap change (amount ${changeUtxo.amount}, owned by an input's keypair) has a blinding that is not derivable from this wallet's viewing key. It was almost certainly built with \`createUtxo\`, whose blinding is random and is written nowhere on chain \u2014 if the caller ever drops the returned note, the funds are unspendable forever. Build it with \`createRecoverableChangeUtxo(amount, keypair, nk, mint, salt, 0)\` and pass the same salt as \`options.chainNoteSalt\`, or use \`swapWithChange\`, which does it for you.`
|
|
9155
|
+
);
|
|
9156
|
+
}
|
|
9157
|
+
}
|
|
8855
9158
|
const swapPoolMint = NATIVE_SOL_MINT;
|
|
8856
9159
|
const pdas = getShieldPoolPDAs(programId, swapPoolMint);
|
|
8857
9160
|
let merkleState = null;
|
|
@@ -9193,7 +9496,6 @@ async function swapUtxo(params, options) {
|
|
|
9193
9496
|
outputCommitments.push(await computeCommitment2(utxo));
|
|
9194
9497
|
}
|
|
9195
9498
|
const chainNoteTimestamp = BigInt(Date.now());
|
|
9196
|
-
const chainNoteSalt = randomChainNoteSalt();
|
|
9197
9499
|
onProgress?.("Computing external data hash...");
|
|
9198
9500
|
const mint = swapPoolMint;
|
|
9199
9501
|
const mintField = pubkeyToFieldElement(mint);
|
|
@@ -9411,6 +9713,9 @@ async function swapUtxo(params, options) {
|
|
|
9411
9713
|
url.searchParams.set("wallet", poolPda.toBase58());
|
|
9412
9714
|
url.searchParams.set("recipient", recipientWallet.toBase58());
|
|
9413
9715
|
url.searchParams.set("sender", recipientWallet.toBase58());
|
|
9716
|
+
url.searchParams.set("pool_mint", mint.toBase58());
|
|
9717
|
+
url.searchParams.set("nullifier0", toHex(bigintToBytes323(inputNullifiers[0])));
|
|
9718
|
+
url.searchParams.set("nullifier1", toHex(bigintToBytes323(inputNullifiers[1])));
|
|
9414
9719
|
const quoteRes = await relayFetch(url.toString());
|
|
9415
9720
|
if (!quoteRes.ok) {
|
|
9416
9721
|
const text = await quoteRes.text();
|
|
@@ -9655,10 +9960,18 @@ async function swapWithChange(inputUtxos, swapAmount, outputMint, recipientAta,
|
|
|
9655
9960
|
throw new Error(`Insufficient balance: input(${totalInput}) < swap(${swapAmount})`);
|
|
9656
9961
|
}
|
|
9657
9962
|
let changeUtxo;
|
|
9963
|
+
let changeNoteSalt;
|
|
9658
9964
|
if (change > BigInt(0)) {
|
|
9659
9965
|
const myKeypair = inputUtxos[0].keypair;
|
|
9660
9966
|
const mint = inputUtxos[0].mintAddress;
|
|
9661
|
-
|
|
9967
|
+
const changeNk = await resolveChainNoteNk(options);
|
|
9968
|
+
if (changeNk) {
|
|
9969
|
+
const salt = randomChangeNoteSalt();
|
|
9970
|
+
changeUtxo = (await createRecoverableChangeUtxo(change, myKeypair, changeNk, mint, salt, 0)).utxo;
|
|
9971
|
+
changeNoteSalt = salt;
|
|
9972
|
+
} else {
|
|
9973
|
+
changeUtxo = await createUtxo(change, myKeypair, mint);
|
|
9974
|
+
}
|
|
9662
9975
|
}
|
|
9663
9976
|
return swapUtxo(
|
|
9664
9977
|
{
|
|
@@ -9670,7 +9983,7 @@ async function swapWithChange(inputUtxos, swapAmount, outputMint, recipientAta,
|
|
|
9670
9983
|
recipientWallet,
|
|
9671
9984
|
minOutputAmount
|
|
9672
9985
|
},
|
|
9673
|
-
options
|
|
9986
|
+
changeNoteSalt !== void 0 ? { ...options, chainNoteSalt: changeNoteSalt } : options
|
|
9674
9987
|
);
|
|
9675
9988
|
}
|
|
9676
9989
|
|
|
@@ -10476,6 +10789,7 @@ async function scanTransactions(opts) {
|
|
|
10476
10789
|
const txs = [];
|
|
10477
10790
|
const swapCtxByCommitment = /* @__PURE__ */ new Map();
|
|
10478
10791
|
const recoveredDepositNotes = [];
|
|
10792
|
+
const recoveredChangeNotes = [];
|
|
10479
10793
|
let processed = 0;
|
|
10480
10794
|
let rpcCallsMade = 0;
|
|
10481
10795
|
onStatus?.(`Scanning ${sigInfos.length} transactions...`);
|
|
@@ -10823,6 +11137,34 @@ async function scanTransactions(opts) {
|
|
|
10823
11137
|
if (debug) console.log(`[DEBUG] ${sigInfo.signature}: deposit recovery failed (${e?.message || e})`);
|
|
10824
11138
|
}
|
|
10825
11139
|
}
|
|
11140
|
+
if (isWithdrawal && compactNote.noteSalt !== void 0 && compactNote.outAmount0 !== void 0 && compactNote.outAmount0 > 0n && compactNote.outPubkey0 !== void 0 && compactNote.outPubkey0 !== 0n) {
|
|
11141
|
+
try {
|
|
11142
|
+
const recoveredChange = await matchChangeNote({
|
|
11143
|
+
viewingKeyNk,
|
|
11144
|
+
noteSalt: compactNote.noteSalt,
|
|
11145
|
+
amount: compactNote.outAmount0,
|
|
11146
|
+
keypair: { privateKey: 0n, publicKey: compactNote.outPubkey0 },
|
|
11147
|
+
mintAddress: new import_web310.PublicKey(asset.mint),
|
|
11148
|
+
outputIndex: 0,
|
|
11149
|
+
// v4 describes output 0, which is where change lands
|
|
11150
|
+
outputCommitments: ixCtx.outputCommitments ?? []
|
|
11151
|
+
});
|
|
11152
|
+
if (recoveredChange) {
|
|
11153
|
+
recoveredChangeNotes.push({
|
|
11154
|
+
...recoveredChange,
|
|
11155
|
+
signature: sigInfo.signature,
|
|
11156
|
+
timestamp: decoded.timestamp
|
|
11157
|
+
});
|
|
11158
|
+
if (debug) {
|
|
11159
|
+
console.log(
|
|
11160
|
+
`[DEBUG] ${sigInfo.signature}: recovered change note (amount=${recoveredChange.amount})`
|
|
11161
|
+
);
|
|
11162
|
+
}
|
|
11163
|
+
}
|
|
11164
|
+
} catch (e) {
|
|
11165
|
+
if (debug) console.log(`[DEBUG] ${sigInfo.signature}: change recovery failed (${e?.message || e})`);
|
|
11166
|
+
}
|
|
11167
|
+
}
|
|
10826
11168
|
txs.push({
|
|
10827
11169
|
txType: decoded.txType,
|
|
10828
11170
|
amount: grossAmount,
|
|
@@ -10928,7 +11270,8 @@ async function scanTransactions(opts) {
|
|
|
10928
11270
|
lastSignature: newestSignature,
|
|
10929
11271
|
rpcCallsMade,
|
|
10930
11272
|
deliveredNotes,
|
|
10931
|
-
recoveredDepositNotes
|
|
11273
|
+
recoveredDepositNotes,
|
|
11274
|
+
recoveredChangeNotes
|
|
10932
11275
|
};
|
|
10933
11276
|
}
|
|
10934
11277
|
function toComplianceReport(result) {
|
|
@@ -11376,12 +11719,14 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11376
11719
|
createCloakError,
|
|
11377
11720
|
createDepositInstruction,
|
|
11378
11721
|
createLogger,
|
|
11722
|
+
createRecoverableChangeUtxo,
|
|
11379
11723
|
createRecoverableDepositUtxo,
|
|
11380
11724
|
createUtxo,
|
|
11381
11725
|
createZeroUtxo,
|
|
11382
11726
|
decryptCompactChainNote,
|
|
11383
11727
|
decryptComplianceMetadataWithMasterKey,
|
|
11384
11728
|
decryptTransactionMetadata,
|
|
11729
|
+
deriveChangeNoteBlinding,
|
|
11385
11730
|
deriveDepositNoteSecrets,
|
|
11386
11731
|
deriveDiversifiedViewingKey,
|
|
11387
11732
|
deriveDiversifier,
|
|
@@ -11467,6 +11812,7 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11467
11812
|
loadPendingDeposits,
|
|
11468
11813
|
loadPendingWithdrawals,
|
|
11469
11814
|
loadVerifiedCircuitArtifacts,
|
|
11815
|
+
matchChangeNote,
|
|
11470
11816
|
matchDepositNote,
|
|
11471
11817
|
matchSwapRefundLeaf,
|
|
11472
11818
|
openRecipientDeliveryNote,
|
|
@@ -11487,6 +11833,7 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11487
11833
|
pubkeyToFieldElement,
|
|
11488
11834
|
pubkeyToLimbs,
|
|
11489
11835
|
randomBytes,
|
|
11836
|
+
randomChangeNoteSalt,
|
|
11490
11837
|
randomDepositNoteSalt,
|
|
11491
11838
|
randomFieldElement,
|
|
11492
11839
|
readMerkleTreeState,
|