@kohaku-eth/tornado-cash 0.0.2-alpha.19 → 0.0.2-alpha.21

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.
@@ -16856,10 +16856,16 @@ async function SecretManager({
16856
16856
  const deriveDelegatorSigner = async ({ path }) => {
16857
16857
  return Promise.resolve(keystore.deriveAt(path));
16858
16858
  };
16859
+ const LEGACY_EPHEMERAL_SALT = asciiToBytes("KOHAKU7702");
16860
+ const deriveLegacyEphemeralSigner = async ({ nullifier }) => {
16861
+ const hash2 = keccak_256(concatBytes2(numberToBytesLE(nullifier, 31), LEGACY_EPHEMERAL_SALT));
16862
+ return `0x${bytesToHex2(hash2)}`;
16863
+ };
16859
16864
  return {
16860
16865
  getDepositSecrets: (params) => deriveSecrets(params),
16861
16866
  deriveEphemeralSigner,
16862
- deriveDelegatorSigner
16867
+ deriveDelegatorSigner,
16868
+ deriveLegacyEphemeralSigner
16863
16869
  };
16864
16870
  }
16865
16871
  function tcPath({ accountIndex, secretType, depositIndex }) {
@@ -17898,10 +17904,10 @@ function getUnexpectedStateShapeWarningMessage(inputState, reducers2, action, un
17898
17904
  function assertReducerShape(reducers2) {
17899
17905
  Object.keys(reducers2).forEach((key) => {
17900
17906
  const reducer = reducers2[key];
17901
- const initialState9 = reducer(void 0, {
17907
+ const initialState10 = reducer(void 0, {
17902
17908
  type: actionTypes_default.INIT
17903
17909
  });
17904
- if (typeof initialState9 === "undefined") {
17910
+ if (typeof initialState10 === "undefined") {
17905
17911
  throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage(12) : `The slice reducer for key "${key}" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined. If you don't want to set a value for this reducer, you can use null instead of undefined.`);
17906
17912
  }
17907
17913
  if (typeof reducer(void 0, {
@@ -19142,7 +19148,7 @@ function createThunkMiddleware(extraArgument) {
19142
19148
  var thunk = createThunkMiddleware();
19143
19149
  var withExtraArgument = createThunkMiddleware;
19144
19150
 
19145
- // ../../node_modules/.pnpm/@reduxjs+toolkit@2.12.0_react@19.2.7/node_modules/@reduxjs/toolkit/dist/redux-toolkit.modern.mjs
19151
+ // ../../node_modules/.pnpm/@reduxjs+toolkit@2.12.0_react@19.2.8/node_modules/@reduxjs/toolkit/dist/redux-toolkit.modern.mjs
19146
19152
  var composeWithDevTools = typeof window !== "undefined" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : function() {
19147
19153
  if (arguments.length === 0) return void 0;
19148
19154
  if (typeof arguments[0] === "object") return compose;
@@ -19763,7 +19769,7 @@ function executeReducerBuilderCallback(builderCallback) {
19763
19769
  function isStateFunction(x) {
19764
19770
  return typeof x === "function";
19765
19771
  }
19766
- function createReducer(initialState9, mapOrBuilderCallback) {
19772
+ function createReducer(initialState10, mapOrBuilderCallback) {
19767
19773
  if (process.env.NODE_ENV !== "production") {
19768
19774
  if (typeof mapOrBuilderCallback === "object") {
19769
19775
  throw new Error(process.env.NODE_ENV === "production" ? formatProdErrorMessage2(8) : "The object notation for `createReducer` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createReducer");
@@ -19771,10 +19777,10 @@ function createReducer(initialState9, mapOrBuilderCallback) {
19771
19777
  }
19772
19778
  let [actionsMap, finalActionMatchers, finalDefaultCaseReducer] = executeReducerBuilderCallback(mapOrBuilderCallback);
19773
19779
  let getInitialState;
19774
- if (isStateFunction(initialState9)) {
19775
- getInitialState = () => freezeDraftable(initialState9());
19780
+ if (isStateFunction(initialState10)) {
19781
+ getInitialState = () => freezeDraftable(initialState10());
19776
19782
  } else {
19777
- const frozenInitialState = freezeDraftable(initialState9);
19783
+ const frozenInitialState = freezeDraftable(initialState10);
19778
19784
  getInitialState = () => frozenInitialState;
19779
19785
  }
19780
19786
  function reducer(state = getInitialState(), action) {
@@ -20429,10 +20435,29 @@ var relayersSelector = createSelector(
20429
20435
  )
20430
20436
  );
20431
20437
  var relayerFeeConfigSelector = (state) => state.relayers.feeConfig;
20432
- var userSecretsSelector = selectEntityMap(
20438
+ var derivedUserSecretsSelector = selectEntityMap(
20433
20439
  (s) => s.userSecrets.byPool,
20434
20440
  deserialize
20435
20441
  );
20442
+ var legacyUserSecretsSelector = selectEntityMap(
20443
+ (s) => s.legacySecrets.byPool,
20444
+ deserialize
20445
+ );
20446
+ var userSecretsSelector = createSelector(
20447
+ [derivedUserSecretsSelector, legacyUserSecretsSelector],
20448
+ (derived, legacy) => {
20449
+ const result = /* @__PURE__ */ new Map();
20450
+ for (const [poolAddress, records] of legacy) {
20451
+ const existing = result.get(poolAddress) ?? [];
20452
+ result.set(poolAddress, [...existing, ...records.map((record) => ({ kind: "legacy", ...record }))]);
20453
+ }
20454
+ for (const [poolAddress, records] of derived) {
20455
+ const existing = result.get(poolAddress) ?? [];
20456
+ result.set(poolAddress, [...existing, ...records.map((record) => ({ kind: "derived", ...record }))]);
20457
+ }
20458
+ return result;
20459
+ }
20460
+ );
20436
20461
 
20437
20462
  // src/state/selectors/deposits.selector.ts
20438
20463
  var myDepositsSelector = createSelector(
@@ -20446,7 +20471,7 @@ var myDepositsSelector = createSelector(
20446
20471
  const commitment = BigInt(r.commitment);
20447
20472
  const deposit = poolDeposits.get(commitment);
20448
20473
  if (deposit) {
20449
- result.set(commitment, { ...deposit, index: r.depositIndex });
20474
+ result.set(commitment, { ...deposit, index: r.kind === "derived" ? r.depositIndex : -1 });
20450
20475
  }
20451
20476
  }
20452
20477
  }
@@ -20827,6 +20852,28 @@ var userSecretsSlice = createSlice({
20827
20852
  var { addUserSecret } = userSecretsSlice.actions;
20828
20853
  var userSecretsReducer = userSecretsSlice.reducer;
20829
20854
 
20855
+ // src/state/slices/legacySecretsSlice.ts
20856
+ var initialState9 = {
20857
+ byPool: []
20858
+ };
20859
+ var legacySecretsSlice = createSlice({
20860
+ name: "legacySecrets",
20861
+ initialState: initialState9,
20862
+ reducers: {
20863
+ addLegacyUserSecret: ({ byPool }, { payload: { poolAddress, record } }) => {
20864
+ const map = new Map(deserialize(byPool));
20865
+ const records = map.get(poolAddress) || [];
20866
+ if (!records.some((r) => r.commitment === record.commitment)) {
20867
+ records.push(record);
20868
+ }
20869
+ map.set(poolAddress, records);
20870
+ return serialize({ byPool: [...map] });
20871
+ }
20872
+ }
20873
+ });
20874
+ var { addLegacyUserSecret } = legacySecretsSlice.actions;
20875
+ var legacySecretsReducer = legacySecretsSlice.reducer;
20876
+
20830
20877
  // src/state/store.ts
20831
20878
  var reducers = {
20832
20879
  deposits: depositsReducer,
@@ -20836,7 +20883,8 @@ var reducers = {
20836
20883
  relayers: relayersReducer,
20837
20884
  instanceRegistryInfo: protocolConfigReducer,
20838
20885
  sync: syncReducer,
20839
- userSecrets: userSecretsReducer
20886
+ userSecrets: userSecretsReducer,
20887
+ legacySecrets: legacySecretsReducer
20840
20888
  };
20841
20889
  var loggerFactory = (logLevel) => (api) => (next) => (action) => {
20842
20890
  const result = next(action);
@@ -20866,11 +20914,11 @@ var loggerFactory = (logLevel) => (api) => (next) => (action) => {
20866
20914
  };
20867
20915
  var storeFactory = ({
20868
20916
  protocolConfig,
20869
- initialState: initialState9,
20917
+ initialState: initialState10,
20870
20918
  logLevel = "error"
20871
20919
  }) => {
20872
20920
  const store = configureStore({
20873
- preloadedState: initialState9,
20921
+ preloadedState: initialState10,
20874
20922
  reducer: reducers,
20875
20923
  middleware: (getDefaultMiddleware) => {
20876
20924
  const defaultMiddleware = getDefaultMiddleware({
@@ -21229,7 +21277,7 @@ var discoverUserEventsThunk = createAsyncThunk(
21229
21277
  const deposits = depositsSelector(state);
21230
21278
  const pools = poolsSelector(state);
21231
21279
  const { chainId } = instanceRegistryInfoSelector(state);
21232
- const userSecrets = userSecretsSelector(state);
21280
+ const userSecrets = derivedUserSecretsSelector(state);
21233
21281
  for (const [poolAddress] of pools) {
21234
21282
  const startIndex = userSecrets.get(poolAddress)?.length ?? 0;
21235
21283
  const poolDeposits = deposits.get(poolAddress);
@@ -21433,7 +21481,7 @@ var createTx = (address, payload, value = BigInt(0)) => {
21433
21481
  init_exports();
21434
21482
  init_encodeAbiParameters2();
21435
21483
 
21436
- // ../../node_modules/.pnpm/@privacy-paymasters+sdk@0.0.4_typescript@5.9.3_zod@4.4.3/node_modules/@privacy-paymasters/sdk/dist/index.js
21484
+ // ../../node_modules/.pnpm/@privacy-paymasters+sdk@0.0.5_typescript@5.9.3_zod@4.4.3/node_modules/@privacy-paymasters/sdk/dist/index.js
21437
21485
  function encodePaymasterData(adapter, adapterData) {
21438
21486
  return encodeAbiParameters2(parseAbiParameters("(address adapter, bytes adapterData)"), [{ adapter, adapterData }]);
21439
21487
  }
@@ -21615,7 +21663,7 @@ var baseGasUnits = {
21615
21663
  preVerificationGas: 100000n,
21616
21664
  verificationGasLimit: 50000n,
21617
21665
  callGasLimit: 300000n,
21618
- paymasterVerificationGasLimit: 350000n,
21666
+ paymasterVerificationGasLimit: 450000n,
21619
21667
  paymasterPostOpGasLimit: 50000n
21620
21668
  };
21621
21669
  function reasonableGasUnits(isERC20) {
@@ -23481,6 +23529,22 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
23481
23529
  );
23482
23530
  const bundlerClient = createPaymasterBundlerClient(bundlerUrl);
23483
23531
  const { standard: { maxFeePerGas, maxPriorityFeePerGas } } = await getUserOperationGasPrice(bundlerClient);
23532
+ const refineGasWithBundler = async (baselineGas2, provisionalUserOperation) => {
23533
+ try {
23534
+ const estimated = await estimateUserOperationGas2(bundlerClient, provisionalUserOperation, entryPointAddress);
23535
+ const buffer2 = (x) => x * 12n / 10n;
23536
+ const orBaseline = (e, b) => e > 0n ? buffer2(e) : b;
23537
+ return {
23538
+ callGasLimit: orBaseline(estimated.callGasLimit, baselineGas2.callGasLimit),
23539
+ verificationGasLimit: orBaseline(estimated.verificationGasLimit, baselineGas2.verificationGasLimit),
23540
+ preVerificationGas: orBaseline(estimated.preVerificationGas, baselineGas2.preVerificationGas),
23541
+ paymasterVerificationGasLimit: orBaseline(estimated.paymasterVerificationGasLimit, baselineGas2.paymasterVerificationGasLimit),
23542
+ paymasterPostOpGasLimit: orBaseline(estimated.paymasterPostOpGasLimit, baselineGas2.paymasterPostOpGasLimit)
23543
+ };
23544
+ } catch {
23545
+ return baselineGas2;
23546
+ }
23547
+ };
23484
23548
  const relayerAddress = BigInt(paymasterAddress);
23485
23549
  const bigintChainId = await dataService.getChainId();
23486
23550
  const { recipient: originalRecipient, ...restWithoutRecipient } = rest;
@@ -23507,11 +23571,13 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
23507
23571
  )
23508
23572
  );
23509
23573
  };
23510
- const ephemeralSigner = async (deposit) => privateKeyToAccount(await secretManager.deriveEphemeralSigner({
23511
- depositIndex: deposit.index,
23512
- chainId: bigintChainId,
23513
- poolAddress: deposit.pool
23514
- }));
23574
+ const ephemeralSigner = async (deposit) => privateKeyToAccount(
23575
+ deposit.kind === "legacy" ? await secretManager.deriveLegacyEphemeralSigner({ nullifier: deposit.nullifier }) : await secretManager.deriveEphemeralSigner({
23576
+ depositIndex: deposit.depositIndex,
23577
+ chainId: bigintChainId,
23578
+ poolAddress: deposit.pool
23579
+ })
23580
+ );
23515
23581
  const resolveBatchDelegator = async () => {
23516
23582
  if (delegation?.mode === "random") return privateKeyToAccount(generatePrivateKey());
23517
23583
  if (delegation?.mode === "deterministic" && delegation.path) {
@@ -23525,19 +23591,36 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
23525
23591
  if (!needsConsolidation) {
23526
23592
  const deposit = deposits[0];
23527
23593
  const signer2 = await resolveIndependentSigner(deposit);
23528
- const gasUnits = reasonableGasUnits(poolInfo.isERC20);
23529
- const fee2 = await quoteFee(computeMinimumViableFee(gasUnits, maxFeePerGas));
23530
- const proof = await prove(deposit, originalRecipient, relayerAddress, fee2);
23531
- const userOperation2 = await buildSignedTornadoUserOp({
23594
+ const baselineGas2 = { ...reasonableGasUnits(poolInfo.isERC20), callGasLimit: 0n };
23595
+ let fee2 = await quoteFee(computeMinimumViableFee(baselineGas2, maxFeePerGas));
23596
+ let gas2 = baselineGas2;
23597
+ let proof = await prove(deposit, originalRecipient, relayerAddress, fee2);
23598
+ let userOperation2 = await buildSignedTornadoUserOp({
23532
23599
  signer: signer2,
23533
23600
  chainId,
23534
23601
  paymasterAddress,
23535
23602
  paymasterData: buildPaymasterData(deposit.pool, proof),
23536
- gas: { ...gasUnits, callGasLimit: 0n },
23603
+ gas: gas2,
23537
23604
  maxFeePerGas,
23538
23605
  maxPriorityFeePerGas,
23539
23606
  nonce: 0n
23540
23607
  });
23608
+ const estimatedGas = await refineGasWithBundler(baselineGas2, userOperation2);
23609
+ if (estimatedGas !== baselineGas2) {
23610
+ gas2 = { ...estimatedGas, callGasLimit: 0n };
23611
+ fee2 = await quoteFee(computeMinimumViableFee(gas2, maxFeePerGas));
23612
+ proof = await prove(deposit, originalRecipient, relayerAddress, fee2);
23613
+ userOperation2 = await buildSignedTornadoUserOp({
23614
+ signer: signer2,
23615
+ chainId,
23616
+ paymasterAddress,
23617
+ paymasterData: buildPaymasterData(deposit.pool, proof),
23618
+ gas: gas2,
23619
+ maxFeePerGas,
23620
+ maxPriorityFeePerGas,
23621
+ nonce: 0n
23622
+ });
23623
+ }
23541
23624
  return [{
23542
23625
  mode: "paymaster",
23543
23626
  proof,
@@ -23606,22 +23689,12 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
23606
23689
  let gas = baselineGas;
23607
23690
  let sponsoringProof = await prove(sponsoringDeposit, senderAddress, relayerAddress, fee);
23608
23691
  let userOperation = await buildOp(gas, fee, buildPaymasterData(sponsoringDeposit.pool, sponsoringProof));
23609
- try {
23610
- const estimated = await estimateUserOperationGas2(bundlerClient, userOperation, entryPointAddress);
23611
- const buffer2 = (x) => x * 12n / 10n;
23612
- const orBaseline = (e, b) => e > 0n ? buffer2(e) : b;
23613
- const refinedGas = {
23614
- callGasLimit: orBaseline(estimated.callGasLimit, baselineGas.callGasLimit),
23615
- verificationGasLimit: orBaseline(estimated.verificationGasLimit, baselineGas.verificationGasLimit),
23616
- preVerificationGas: orBaseline(estimated.preVerificationGas, baselineGas.preVerificationGas),
23617
- paymasterVerificationGasLimit: orBaseline(estimated.paymasterVerificationGasLimit, baselineGas.paymasterVerificationGasLimit),
23618
- paymasterPostOpGasLimit: orBaseline(estimated.paymasterPostOpGasLimit, baselineGas.paymasterPostOpGasLimit)
23619
- };
23620
- fee = await quoteFee(computeMinimumViableFee(refinedGas, maxFeePerGas));
23692
+ const refinedGas = await refineGasWithBundler(baselineGas, userOperation);
23693
+ if (refinedGas !== baselineGas) {
23621
23694
  gas = refinedGas;
23695
+ fee = await quoteFee(computeMinimumViableFee(gas, maxFeePerGas));
23622
23696
  sponsoringProof = await prove(sponsoringDeposit, senderAddress, relayerAddress, fee);
23623
23697
  userOperation = await buildOp(gas, fee, buildPaymasterData(sponsoringDeposit.pool, sponsoringProof));
23624
- } catch {
23625
23698
  }
23626
23699
  return [{
23627
23700
  mode: "paymaster",
@@ -23703,7 +23776,7 @@ var getDepositPayloadThunk = createAsyncThunk(
23703
23776
  const state = getState();
23704
23777
  const pools = poolsSelector(state);
23705
23778
  const { chainId } = instanceRegistryInfoSelector(state);
23706
- const userSecrets = userSecretsSelector(state);
23779
+ const userSecrets = derivedUserSecretsSelector(state);
23707
23780
  const poolsCandidates = Array.from(pools.values()).filter((p) => p.asset === asset);
23708
23781
  if (poolsCandidates.length === 0) throw new Error(`No pools available for asset ${addressToHex(asset)}`);
23709
23782
  const poolsToDepositInto = calculatePoolsDeposits(poolsCandidates, amount, strategy);
@@ -23752,6 +23825,62 @@ var getDepositPayloadThunk = createAsyncThunk(
23752
23825
  }
23753
23826
  );
23754
23827
 
23828
+ // src/account/legacyNote.ts
23829
+ init_utils2();
23830
+ var NOTE_REGEX = /^tornado-([a-zA-Z0-9]+)-([0-9.]+)-(\d+)-0x([0-9a-fA-F]+)$/;
23831
+ function parseLegacyNote(note) {
23832
+ const match = NOTE_REGEX.exec(note.trim());
23833
+ if (!match) {
23834
+ throw new Error(`Invalid tornado cash note: ${note}`);
23835
+ }
23836
+ const [, currency, denomination, chainId, preimageHex] = match;
23837
+ const preimageBytes = hexToBytes2(preimageHex);
23838
+ if (preimageBytes.length !== 62) {
23839
+ throw new Error(`Invalid tornado cash note preimage length: ${note}`);
23840
+ }
23841
+ const nullifierBytes = preimageBytes.subarray(0, 31);
23842
+ const saltBytes = preimageBytes.subarray(31, 62);
23843
+ return {
23844
+ currency,
23845
+ denomination,
23846
+ chainId: BigInt(chainId),
23847
+ nullifier: bytesToNumberLE(nullifierBytes),
23848
+ salt: bytesToNumberLE(saltBytes),
23849
+ commitment: pedersenHash2(preimageBytes),
23850
+ nullifierHash: pedersenHash2(nullifierBytes)
23851
+ };
23852
+ }
23853
+
23854
+ // src/state/thunks/importLegacyNotesThunk.ts
23855
+ var importLegacyNotesThunk = createAsyncThunk(
23856
+ "userSecrets/importLegacy",
23857
+ async ({ notes }, { getState, dispatch }) => {
23858
+ const state = getState();
23859
+ const deposits = depositsSelector(state);
23860
+ const { chainId } = instanceRegistryInfoSelector(state);
23861
+ return notes.map((note) => {
23862
+ const parsed = parseLegacyNote(note);
23863
+ if (parsed.chainId !== chainId) {
23864
+ return { note, status: "wrong-chain" };
23865
+ }
23866
+ const matchedPool = [...deposits].find(([, poolDeposits]) => poolDeposits.has(parsed.commitment))?.[0];
23867
+ if (!matchedPool) {
23868
+ return { note, status: "not-found" };
23869
+ }
23870
+ dispatch(addLegacyUserSecret({
23871
+ poolAddress: matchedPool,
23872
+ record: {
23873
+ commitment: parsed.commitment,
23874
+ nullifierHash: parsed.nullifierHash,
23875
+ nullifier: parsed.nullifier,
23876
+ salt: parsed.salt
23877
+ }
23878
+ }));
23879
+ return { note, status: "imported", poolAddress: matchedPool };
23880
+ });
23881
+ }
23882
+ );
23883
+
23755
23884
  // src/state/state-manager.ts
23756
23885
  var ETH_SEPOLIA_CHAIN_ID = 11155111n;
23757
23886
  var getStoreKey = ({
@@ -23766,6 +23895,10 @@ var initializeSelectors = (store) => ({
23766
23895
  getAllNotes: () => allNotesSelector(store.getState())
23767
23896
  },
23768
23897
  getPublicState: () => {
23898
+ const { userSecrets, legacySecrets, ...publicState } = store.getState();
23899
+ return publicState;
23900
+ },
23901
+ getPrivateState: () => {
23769
23902
  const { userSecrets, ...publicState } = store.getState();
23770
23903
  return publicState;
23771
23904
  }
@@ -23795,13 +23928,13 @@ var storeByChainAndEntrypoint = ({
23795
23928
  const rawStoredState = storageToSyncTo ? await storageToSyncTo.get(storageKey) : void 0;
23796
23929
  const storedState = rawStoredState ? JSON.parse(rawStoredState) : void 0;
23797
23930
  const snapshotInitialState = storedState || !resolveInitialState ? void 0 : (await resolveInitialState())[storageKey];
23798
- let initialState9 = storedState || snapshotInitialState;
23799
- if (!initialState9 && getChainStoreParams.chainId === ETH_SEPOLIA_CHAIN_ID) {
23800
- initialState9 = await Promise.resolve().then(() => __toESM(require_state_11155111_minimal(), 1)).then((a) => a["tornado-cash-state-11155111-447664927873626138772898946646079239273904189887"]);
23931
+ let initialState10 = storedState || snapshotInitialState;
23932
+ if (!initialState10 && getChainStoreParams.chainId === ETH_SEPOLIA_CHAIN_ID) {
23933
+ initialState10 = await Promise.resolve().then(() => __toESM(require_state_11155111_minimal(), 1)).then((a) => a["tornado-cash-state-11155111-447664927873626138772898946646079239273904189887"]);
23801
23934
  }
23802
23935
  const store = storeFactory({
23803
23936
  protocolConfig,
23804
- initialState: initialState9
23937
+ initialState: initialState10
23805
23938
  });
23806
23939
  store.dispatch(setRelayerFeeConfig(relayerConfig));
23807
23940
  storeWithSelectors = initializeSelectors(store);
@@ -23830,14 +23963,14 @@ var storeStateManager = async ({
23830
23963
  paymasterConfig,
23831
23964
  proverFactory,
23832
23965
  storageToSyncTo,
23833
- initialState: initialState9,
23966
+ initialState: initialState10,
23834
23967
  protocolConfig,
23835
23968
  relayerConfig
23836
23969
  }) => {
23837
23970
  const secretManager = await secretManagerFactory();
23838
23971
  const { getChainStore, getAllStores } = storeByChainAndEntrypoint({
23839
23972
  storageToSyncTo,
23840
- initialState: initialState9
23973
+ initialState: initialState10
23841
23974
  });
23842
23975
  const getChainInfo = async () => {
23843
23976
  const chainId = await dataService.getChainId();
@@ -23851,6 +23984,14 @@ var storeStateManager = async ({
23851
23984
  }
23852
23985
  };
23853
23986
  };
23987
+ const persistStateIfAvailable = async (chainInfo, store) => {
23988
+ if (storageToSyncTo) {
23989
+ await storageToSyncTo.set(
23990
+ getStoreStorageKey(chainInfo),
23991
+ JSON.stringify(store.getPrivateState())
23992
+ );
23993
+ }
23994
+ };
23854
23995
  return {
23855
23996
  sync: async () => {
23856
23997
  const chainInfo = await getChainInfo();
@@ -23866,12 +24007,7 @@ var storeStateManager = async ({
23866
24007
  })
23867
24008
  )
23868
24009
  );
23869
- if (storageToSyncTo) {
23870
- await storageToSyncTo.set(
23871
- getStoreStorageKey(chainInfo),
23872
- JSON.stringify(store.getPublicState())
23873
- );
23874
- }
24010
+ await persistStateIfAvailable(chainInfo, store);
23875
24011
  },
23876
24012
  getBalances: async (assets) => {
23877
24013
  const { selectors: { specificAssetsBalanceSelector: specificAssetsBalanceSelector2 } } = await getChainStore(await getChainInfo());
@@ -23937,6 +24073,15 @@ var storeStateManager = async ({
23937
24073
  )
23938
24074
  );
23939
24075
  },
24076
+ importNotes: async ({ notes }) => {
24077
+ const chainInfo = await getChainInfo();
24078
+ const store = await getChainStore(chainInfo);
24079
+ const result = unwrapResult(
24080
+ await store.dispatch(importLegacyNotesThunk({ notes }))
24081
+ );
24082
+ await persistStateIfAvailable(chainInfo, store);
24083
+ return result;
24084
+ },
23940
24085
  dumpState: () => getAllStores()
23941
24086
  };
23942
24087
  };
@@ -23948,12 +24093,12 @@ function getStateManager() {
23948
24093
  return _stateManager;
23949
24094
  }
23950
24095
  var workerApi = {
23951
- async init(provider, relayerClient, keystore, rawStorage, initialState9, artifactsLoader, externalSyncProvider, { protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }) {
24096
+ async init(provider, relayerClient, keystore, rawStorage, initialState10, artifactsLoader, secretManager, externalSyncProvider, { protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }) {
23952
24097
  const storage = rawStorage;
23953
24098
  const dataService = new DataService({ provider });
23954
24099
  _stateManager = await storeStateManager({
23955
24100
  paymasterConfig,
23956
- secretManagerFactory: () => SecretManager({ host: { keystore }, accountIndex }),
24101
+ secretManagerFactory: () => secretManager ? Promise.resolve(secretManager) : SecretManager({ host: { keystore }, accountIndex }),
23957
24102
  dataService,
23958
24103
  syncService: new SyncService({ dataService, externalSyncProvider, minExternalSyncBlocksAmount }),
23959
24104
  relayerClient,
@@ -23961,7 +24106,7 @@ var workerApi = {
23961
24106
  storageToSyncTo: storage,
23962
24107
  protocolConfig,
23963
24108
  relayerConfig,
23964
- initialState: initialState9
24109
+ initialState: initialState10
23965
24110
  });
23966
24111
  },
23967
24112
  sync() {
@@ -23976,6 +24121,9 @@ var workerApi = {
23976
24121
  getDepositPayload(params) {
23977
24122
  return getStateManager().getDepositPayload(params);
23978
24123
  },
24124
+ importNotes(params) {
24125
+ return getStateManager().importNotes(params);
24126
+ },
23979
24127
  getWithdrawalPayloads(params, tailCalls) {
23980
24128
  const fullParams = params.mode === "paymaster" && tailCalls ? { ...params, tailCalls } : params;
23981
24129
  return getStateManager().getWithdrawalPayloads(fullParams);
@@ -7,6 +7,8 @@ import * as _kohaku_eth_provider from '@kohaku-eth/provider';
7
7
  import { TxData } from '@kohaku-eth/provider';
8
8
  import { Address as Address$1 } from 'ox/Address';
9
9
 
10
+ type Nullifier = bigint & {};
11
+ type NullifierHash = bigint & {};
10
12
  type Address = bigint & {};
11
13
  type Commitment = bigint & {};
12
14
  interface IContract {
@@ -30,6 +32,41 @@ interface ProtocolConfigState {
30
32
  type RootState = ReturnType<ReturnType<typeof combineReducers<typeof reducers>>>;
31
33
  type PublicRootState = Omit<RootState, 'userSecrets'>;
32
34
 
35
+ interface Secret {
36
+ nullifier: Nullifier;
37
+ salt: bigint;
38
+ commitment: Commitment;
39
+ nullifierHash: NullifierHash;
40
+ }
41
+ type BaseDeriveSecretParams = {
42
+ poolAddress: bigint;
43
+ chainId: bigint;
44
+ };
45
+ type DeriveDepositSecretParams = BaseDeriveSecretParams & {
46
+ depositIndex: number;
47
+ };
48
+ interface ISecretManager {
49
+ getDepositSecrets: (params: DeriveDepositSecretParams) => Promise<Secret>;
50
+ deriveEphemeralSigner: (params: DeriveDepositSecretParams) => Promise<`0x${string}`>;
51
+ /**
52
+ * Derives a delegator key from a classical wallet BIP-32 `path`, WITHOUT the
53
+ * `coalesceSecret` privacy transform, so it resolves to a recoverable,
54
+ * classical Ethereum address. Used for the tail-call batch delegator when the
55
+ * integrator supplies a wallet path (see `paymasterWithdrawThunk`).
56
+ */
57
+ deriveDelegatorSigner: (params: {
58
+ path: string;
59
+ }) => Promise<`0x${string}`>;
60
+ /**
61
+ * Derives the ephemeral signer for an imported legacy note. Legacy secrets
62
+ * have no keystore-derived `depositIndex`, so this is a pure function of
63
+ * the note's own nullifier instead of a BIP-32 derivation.
64
+ */
65
+ deriveLegacyEphemeralSigner: (params: {
66
+ nullifier: Nullifier;
67
+ }) => Promise<`0x${string}`>;
68
+ }
69
+
33
70
  interface IBaseEvent {
34
71
  blockNumber: bigint;
35
72
  transactionHash: bigint;
@@ -91,6 +128,18 @@ interface IRelayerClient {
91
128
  withdraw(relayerUrl: string, body: ITornadoWithdrawRequest): Promise<ITornadoWithdrawResponse>;
92
129
  }
93
130
 
131
+ type ImportNoteResult = {
132
+ note: string;
133
+ status: 'imported';
134
+ poolAddress: Address;
135
+ } | {
136
+ note: string;
137
+ status: 'wrong-chain';
138
+ } | {
139
+ note: string;
140
+ status: 'not-found';
141
+ };
142
+
94
143
  interface TornadoProveOutput {
95
144
  proof: `0x${string}`;
96
145
  args: [
@@ -241,11 +290,14 @@ interface WorkerInitOptions {
241
290
 
242
291
  declare function loadStateManagerWorker(workerUrl?: string | URL): {
243
292
  remote: comlink.Remote<{
244
- init(provider: _kohaku_eth_provider.EthereumProvider, relayerClient: IRelayerClient, keystore: _kohaku_eth_plugins.Keystore, rawStorage: Omit<_kohaku_eth_plugins.Storage, "_brand">, initialState: () => Promise<Record<string, PublicRootState>>, artifactsLoader: () => Promise<ITornadoArtifacts>, externalSyncProvider: ExternalSyncClient | undefined, { protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }: WorkerInitOptions): Promise<void>;
293
+ init(provider: _kohaku_eth_provider.EthereumProvider, relayerClient: IRelayerClient, keystore: _kohaku_eth_plugins.Keystore, rawStorage: Omit<_kohaku_eth_plugins.Storage, "_brand">, initialState: () => Promise<Record<string, PublicRootState>>, artifactsLoader: () => Promise<ITornadoArtifacts>, secretManager: ISecretManager | undefined, externalSyncProvider: ExternalSyncClient | undefined, { protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }: WorkerInitOptions): Promise<void>;
245
294
  sync(): Promise<void>;
246
295
  getBalances(assets?: Address[]): Promise<Map<Address, bigint>>;
247
296
  getNotes(params: IGetNotesParams): Promise<TCNote[]>;
248
297
  getDepositPayload(params: IDepositOperationParams): Promise<_kohaku_eth_provider.TxData[]>;
298
+ importNotes(params: {
299
+ notes: string[];
300
+ }): Promise<ImportNoteResult[]>;
249
301
  getWithdrawalPayloads(params: IWithdrawapOperationParams, tailCalls?: IPaymasterWithdrawParams["tailCalls"]): Promise<IWithdrawalPayload[]>;
250
302
  dumpState(): Record<StoreStorageKey, Omit<RootState, "userSecrets">>;
251
303
  }>;
@@ -8,6 +8,8 @@ import { TxData } from '@kohaku-eth/provider';
8
8
  import { Address as Address$1 } from 'ox/Address';
9
9
  import { Worker } from 'worker_threads';
10
10
 
11
+ type Nullifier = bigint & {};
12
+ type NullifierHash = bigint & {};
11
13
  type Address = bigint & {};
12
14
  type Commitment = bigint & {};
13
15
  interface IContract {
@@ -31,6 +33,41 @@ interface ProtocolConfigState {
31
33
  type RootState = ReturnType<ReturnType<typeof combineReducers<typeof reducers>>>;
32
34
  type PublicRootState = Omit<RootState, 'userSecrets'>;
33
35
 
36
+ interface Secret {
37
+ nullifier: Nullifier;
38
+ salt: bigint;
39
+ commitment: Commitment;
40
+ nullifierHash: NullifierHash;
41
+ }
42
+ type BaseDeriveSecretParams = {
43
+ poolAddress: bigint;
44
+ chainId: bigint;
45
+ };
46
+ type DeriveDepositSecretParams = BaseDeriveSecretParams & {
47
+ depositIndex: number;
48
+ };
49
+ interface ISecretManager {
50
+ getDepositSecrets: (params: DeriveDepositSecretParams) => Promise<Secret>;
51
+ deriveEphemeralSigner: (params: DeriveDepositSecretParams) => Promise<`0x${string}`>;
52
+ /**
53
+ * Derives a delegator key from a classical wallet BIP-32 `path`, WITHOUT the
54
+ * `coalesceSecret` privacy transform, so it resolves to a recoverable,
55
+ * classical Ethereum address. Used for the tail-call batch delegator when the
56
+ * integrator supplies a wallet path (see `paymasterWithdrawThunk`).
57
+ */
58
+ deriveDelegatorSigner: (params: {
59
+ path: string;
60
+ }) => Promise<`0x${string}`>;
61
+ /**
62
+ * Derives the ephemeral signer for an imported legacy note. Legacy secrets
63
+ * have no keystore-derived `depositIndex`, so this is a pure function of
64
+ * the note's own nullifier instead of a BIP-32 derivation.
65
+ */
66
+ deriveLegacyEphemeralSigner: (params: {
67
+ nullifier: Nullifier;
68
+ }) => Promise<`0x${string}`>;
69
+ }
70
+
34
71
  interface IBaseEvent {
35
72
  blockNumber: bigint;
36
73
  transactionHash: bigint;
@@ -92,6 +129,18 @@ interface IRelayerClient {
92
129
  withdraw(relayerUrl: string, body: ITornadoWithdrawRequest): Promise<ITornadoWithdrawResponse>;
93
130
  }
94
131
 
132
+ type ImportNoteResult = {
133
+ note: string;
134
+ status: 'imported';
135
+ poolAddress: Address;
136
+ } | {
137
+ note: string;
138
+ status: 'wrong-chain';
139
+ } | {
140
+ note: string;
141
+ status: 'not-found';
142
+ };
143
+
95
144
  interface TornadoProveOutput {
96
145
  proof: `0x${string}`;
97
146
  args: [
@@ -242,11 +291,14 @@ interface WorkerInitOptions {
242
291
 
243
292
  declare function loadStateManagerWorker(workerUrl?: string | URL): {
244
293
  remote: comlink.Remote<{
245
- init(provider: _kohaku_eth_provider.EthereumProvider, relayerClient: IRelayerClient, keystore: _kohaku_eth_plugins.Keystore, rawStorage: Omit<_kohaku_eth_plugins.Storage, "_brand">, initialState: () => Promise<Record<string, PublicRootState>>, artifactsLoader: () => Promise<ITornadoArtifacts>, externalSyncProvider: ExternalSyncClient | undefined, { protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }: WorkerInitOptions): Promise<void>;
294
+ init(provider: _kohaku_eth_provider.EthereumProvider, relayerClient: IRelayerClient, keystore: _kohaku_eth_plugins.Keystore, rawStorage: Omit<_kohaku_eth_plugins.Storage, "_brand">, initialState: () => Promise<Record<string, PublicRootState>>, artifactsLoader: () => Promise<ITornadoArtifacts>, secretManager: ISecretManager | undefined, externalSyncProvider: ExternalSyncClient | undefined, { protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }: WorkerInitOptions): Promise<void>;
246
295
  sync(): Promise<void>;
247
296
  getBalances(assets?: Address[]): Promise<Map<Address, bigint>>;
248
297
  getNotes(params: IGetNotesParams): Promise<TCNote[]>;
249
298
  getDepositPayload(params: IDepositOperationParams): Promise<_kohaku_eth_provider.TxData[]>;
299
+ importNotes(params: {
300
+ notes: string[];
301
+ }): Promise<ImportNoteResult[]>;
250
302
  getWithdrawalPayloads(params: IWithdrawapOperationParams, tailCalls?: IPaymasterWithdrawParams["tailCalls"]): Promise<IWithdrawalPayload[]>;
251
303
  dumpState(): Record<StoreStorageKey, Omit<RootState, "userSecrets">>;
252
304
  }>;