@kohaku-eth/tornado-cash 0.0.2-alpha.12 → 0.0.2-alpha.14
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/dist/index.d.ts +102 -18
- package/dist/index.js +71 -114
- package/dist/merkle-tree.browser.js +1 -1
- package/dist/merkle-tree.node.js +1 -1
- package/dist/state-manager.worker.js +17049 -17987
- package/dist/state-manager.worker.node.js +16238 -17176
- package/dist/worker-loader.browser.d.ts +56 -8
- package/dist/worker-loader.node.d.ts +56 -8
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Broadcaster } from '@kohaku-eth/plugins/broadcaster';
|
|
2
|
-
import { Host, ChainId, Storage, PrivateOperation, PublicOperation, AssetAmount, ERC20AssetId, PluginInstance,
|
|
2
|
+
import { Host, ExternalRawEvent, ChainId, Storage, PrivateOperation, PublicOperation, AccountId, AssetAmount, ERC20AssetId, PluginInstance, UnshieldOptions } from '@kohaku-eth/plugins';
|
|
3
|
+
import { TxData } from '@kohaku-eth/provider';
|
|
3
4
|
import { combineReducers } from '@reduxjs/toolkit';
|
|
4
5
|
import { ParseAbiItem, SignedAuthorization, Hash, Address as Address$2 } from 'viem';
|
|
5
|
-
import { TxData } from '@kohaku-eth/provider';
|
|
6
6
|
import { Address as Address$1 } from 'ox/Address';
|
|
7
|
+
import { Hex } from 'ox/Hex';
|
|
7
8
|
|
|
8
9
|
type Nullifier$1 = bigint & {};
|
|
9
10
|
type NullifierHash = bigint & {};
|
|
@@ -190,7 +191,7 @@ declare const INSTANCE_REGISTRY_EVENT_SIGNATURES: {
|
|
|
190
191
|
};
|
|
191
192
|
|
|
192
193
|
type IEventsMap = Record<string, ParseAbiItem<string>>;
|
|
193
|
-
interface IGetEventsParams<T> {
|
|
194
|
+
interface IGetEventsParams$1<T> {
|
|
194
195
|
events: T | T[];
|
|
195
196
|
fromBlock: bigint;
|
|
196
197
|
toBlock?: bigint;
|
|
@@ -211,7 +212,7 @@ type IGroupedEvents<NamesTable extends Record<string, unknown>> = {
|
|
|
211
212
|
};
|
|
212
213
|
type GetEventsFn<EventsMap extends IEventsMap, ParsedEvents extends {
|
|
213
214
|
[key in keyof EventsMap]: unknown;
|
|
214
|
-
}> = <const T extends keyof ParsedEvents = never>(params: IGetEventsParams<T>) => Promise<Pick<IGroupedEvents<ParsedEvents>, T> & {
|
|
215
|
+
}> = <const T extends keyof ParsedEvents = never>(params: IGetEventsParams$1<T>) => Promise<Pick<IGroupedEvents<ParsedEvents>, T> & {
|
|
215
216
|
fromBlock: bigint;
|
|
216
217
|
toBlock: bigint;
|
|
217
218
|
}>;
|
|
@@ -220,7 +221,6 @@ interface IPoolConfig {
|
|
|
220
221
|
isERC20: boolean;
|
|
221
222
|
token: Address;
|
|
222
223
|
state: 0 | 1;
|
|
223
|
-
uniswapPoolSwappingFee: number;
|
|
224
224
|
protocolFeePercentage: number;
|
|
225
225
|
denomination: bigint;
|
|
226
226
|
rootHistorySize: number;
|
|
@@ -233,6 +233,14 @@ interface IRelayerAggregatorData {
|
|
|
233
233
|
}
|
|
234
234
|
interface IDataService {
|
|
235
235
|
getPoolEvents: GetEventsFn<typeof POOL_EVENTS_SIGNATURES, IPoolEvents>;
|
|
236
|
+
getBlockNumber(): Promise<bigint>;
|
|
237
|
+
parsePoolEvents(events: ExternalRawEvent[]): {
|
|
238
|
+
Deposited: IRawDepositEvent[];
|
|
239
|
+
Withdrawn: IRawWithdrawalEvent[];
|
|
240
|
+
};
|
|
241
|
+
parseRelayerRegistryEvents(events: ExternalRawEvent[]): {
|
|
242
|
+
RelayerRegistered: IRelayerRegisteredEvent[];
|
|
243
|
+
};
|
|
236
244
|
getRelayerRegistryEvents: GetEventsFn<typeof RELAYER_REGISTRY_EVENTS_SIGNATURES, IRelayerRegistryEvents>;
|
|
237
245
|
getInstanceRegistryEvents: GetEventsFn<typeof INSTANCE_REGISTRY_EVENT_SIGNATURES, IInstanceRegistryEvents>;
|
|
238
246
|
getAsset(assetAddress: Address): Promise<IAsset>;
|
|
@@ -249,7 +257,47 @@ interface IDataService {
|
|
|
249
257
|
getLatestBlockTimestamp(): Promise<bigint>;
|
|
250
258
|
getRelayerData(aggregatorAddress: Address, relayerNameHashes: bigint[], subdomains: string[]): Promise<IRelayerAggregatorData[]>;
|
|
251
259
|
getAccountNonce(accountAddress: Address): Promise<number>;
|
|
252
|
-
|
|
260
|
+
quoteWeiInToken(paymasterAddress: Address, feeToken: Address, weiAmount: bigint): Promise<bigint>;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Identifies one contract to sync from a given block. */
|
|
264
|
+
interface IGetEventsParams {
|
|
265
|
+
chainId: bigint;
|
|
266
|
+
address: Address;
|
|
267
|
+
fromBlock: bigint;
|
|
268
|
+
}
|
|
269
|
+
interface IGetPoolEventsResult {
|
|
270
|
+
Deposited: IRawDepositEvent[];
|
|
271
|
+
Withdrawn: IRawWithdrawalEvent[];
|
|
272
|
+
/** Highest block the returned events are synced up to. */
|
|
273
|
+
toBlock: bigint;
|
|
274
|
+
}
|
|
275
|
+
interface IGetRelayerRegistryEventsResult {
|
|
276
|
+
RelayerRegistered: IRelayerRegisteredEvent[];
|
|
277
|
+
/** Highest block the returned events are synced up to. */
|
|
278
|
+
toBlock: bigint;
|
|
279
|
+
}
|
|
280
|
+
interface ISyncService {
|
|
281
|
+
/**
|
|
282
|
+
* Fetches a single pool's `Deposited`/`Withdrawn` events from `fromBlock`.
|
|
283
|
+
* Uses the external sync provider for the bulk of a large range and the chain
|
|
284
|
+
* for the remaining tail; falls back to a chain-only fetch otherwise.
|
|
285
|
+
*/
|
|
286
|
+
getPoolEvents(params: IGetEventsParams): Promise<IGetPoolEventsResult>;
|
|
287
|
+
/**
|
|
288
|
+
* Fetches the relayer registry's `RelayerRegistered` events from `fromBlock`,
|
|
289
|
+
* with the same external-then-chain strategy as {@link getPoolEvents}.
|
|
290
|
+
*/
|
|
291
|
+
getRelayerRegistryEvents(params: IGetEventsParams): Promise<IGetRelayerRegistryEventsResult>;
|
|
292
|
+
/**
|
|
293
|
+
* Resolves a pool's scan-start block. Uses the external provider's first
|
|
294
|
+
* covered block when available (an O(1) lookup), else falls back to the
|
|
295
|
+
* on-chain deployment-block binary search.
|
|
296
|
+
*/
|
|
297
|
+
getPoolDeploymentBlock(params: {
|
|
298
|
+
chainId: bigint;
|
|
299
|
+
address: Address;
|
|
300
|
+
}): Promise<bigint>;
|
|
253
301
|
}
|
|
254
302
|
|
|
255
303
|
type SpecificAssetBalanceFn<isAsync extends boolean = false> = <const Adresses extends Address | Address[] = Address[], ReturnType = Adresses extends unknown[] ? Map<Address, bigint> : bigint>(assetAddress?: Adresses) => isAsync extends true ? Promise<ReturnType> : ReturnType;
|
|
@@ -289,6 +337,7 @@ interface IRelayerFeeConfig {
|
|
|
289
337
|
interface StoreFactoryParams {
|
|
290
338
|
secretManagerFactory: () => Promise<ISecretManager>;
|
|
291
339
|
dataService: IDataService;
|
|
340
|
+
syncService: ISyncService;
|
|
292
341
|
relayerClient: IRelayerClient;
|
|
293
342
|
paymasterConfig: IChainsPaymastersConfig;
|
|
294
343
|
storageToSyncTo?: Storage;
|
|
@@ -303,6 +352,36 @@ declare enum DepositStrategy {
|
|
|
303
352
|
MinFee = 1
|
|
304
353
|
}
|
|
305
354
|
|
|
355
|
+
interface SerializedAuth {
|
|
356
|
+
address: Address$1;
|
|
357
|
+
chainId: Hex;
|
|
358
|
+
nonce: Hex;
|
|
359
|
+
r: Hex;
|
|
360
|
+
s: Hex;
|
|
361
|
+
yParity: Hex;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* A userOp serialized to the hex shape expected by `eth_sendUserOperation`, so
|
|
365
|
+
* it can be carried as plain (JSON-serializable) data from the prepare phase
|
|
366
|
+
* (thunk) to the broadcast phase.
|
|
367
|
+
*/
|
|
368
|
+
interface SerializedUserOperation {
|
|
369
|
+
sender: `0x${string}`;
|
|
370
|
+
nonce: `0x${string}`;
|
|
371
|
+
callData: `0x${string}`;
|
|
372
|
+
callGasLimit: `0x${string}`;
|
|
373
|
+
verificationGasLimit: `0x${string}`;
|
|
374
|
+
preVerificationGas: `0x${string}`;
|
|
375
|
+
maxFeePerGas: `0x${string}`;
|
|
376
|
+
maxPriorityFeePerGas: `0x${string}`;
|
|
377
|
+
paymaster?: `0x${string}`;
|
|
378
|
+
paymasterVerificationGasLimit?: `0x${string}`;
|
|
379
|
+
paymasterPostOpGasLimit?: `0x${string}`;
|
|
380
|
+
paymasterData?: `0x${string}`;
|
|
381
|
+
signature: `0x${string}`;
|
|
382
|
+
eip7702Auth?: SerializedAuth;
|
|
383
|
+
}
|
|
384
|
+
|
|
306
385
|
interface SignedDelegation {
|
|
307
386
|
senderAddress: `0x${string}`;
|
|
308
387
|
authorization: SignedAuthorization;
|
|
@@ -322,8 +401,7 @@ interface IGenericPaymasterWithdrawalPayload {
|
|
|
322
401
|
paymasterAddress: `0x${string}`;
|
|
323
402
|
entryPointAddress: `0x${string}`;
|
|
324
403
|
bundlerUrl: string;
|
|
325
|
-
|
|
326
|
-
delegation?: SignedDelegation;
|
|
404
|
+
userOperation: SerializedUserOperation;
|
|
327
405
|
}
|
|
328
406
|
interface PaymasterBroadcastResult {
|
|
329
407
|
userOpHash: Hash;
|
|
@@ -377,6 +455,12 @@ interface TCProtocolParams {
|
|
|
377
455
|
artifactsLoader?: () => Promise<ITornadoArtifacts>;
|
|
378
456
|
initialState?: () => Promise<Record<string, PublicRootState>>;
|
|
379
457
|
stateManagerWorkerUrl?: string;
|
|
458
|
+
/**
|
|
459
|
+
* When a pool is at least this many blocks behind, use the host's
|
|
460
|
+
* `externalSyncProvider` (if any) for the bulk of the sync instead of the
|
|
461
|
+
* chain. Omit to always sync from the chain.
|
|
462
|
+
*/
|
|
463
|
+
minExternalSyncBlocksAmount?: number;
|
|
380
464
|
}
|
|
381
465
|
interface IBaseOperationParams {
|
|
382
466
|
}
|
|
@@ -396,6 +480,7 @@ interface IRelayerWithdrawParams extends IWithdrawBaseParams {
|
|
|
396
480
|
interface IPaymasterWithdrawParams extends IWithdrawBaseParams {
|
|
397
481
|
mode: 'paymaster';
|
|
398
482
|
delegation?: DelegationConfig;
|
|
483
|
+
tailCalls?: (address: AccountId) => Promise<TxData[]>;
|
|
399
484
|
}
|
|
400
485
|
type IWithdrawapOperationParams = IRelayerWithdrawParams | IPaymasterWithdrawParams;
|
|
401
486
|
interface IGetNotesParams extends IBaseOperationParams {
|
|
@@ -445,7 +530,7 @@ type TCBroadcaster = Broadcaster<TCPrivateOperation, ITornadoWithdrawResponse[]>
|
|
|
445
530
|
interface TCBaseCredential {
|
|
446
531
|
accountIndex: number;
|
|
447
532
|
}
|
|
448
|
-
interface TCPluginParameters extends TCBroadcasterParameters, TCBaseCredential, Pick<TCProtocolParams, 'initialState'> {
|
|
533
|
+
interface TCPluginParameters extends TCBroadcasterParameters, TCBaseCredential, Pick<TCProtocolParams, 'initialState' | 'minExternalSyncBlocksAmount'> {
|
|
449
534
|
protocolConfig: TCProtocolConfig;
|
|
450
535
|
relayerConfig?: IRelayerFeeConfig;
|
|
451
536
|
stateManagerWorkerUrl?: string;
|
|
@@ -454,11 +539,11 @@ interface TCPluginParameters extends TCBroadcasterParameters, TCBaseCredential,
|
|
|
454
539
|
type TCAddress = Address$1;
|
|
455
540
|
type TCAssetAmount<Tag extends string | undefined = undefined> = AssetAmount<ERC20AssetId, bigint, Tag>;
|
|
456
541
|
type TCAssetBalance = TCAssetAmount;
|
|
457
|
-
interface TCRelayerUnshieldOptions {
|
|
542
|
+
interface TCRelayerUnshieldOptions extends UnshieldOptions {
|
|
458
543
|
mode: 'relayer';
|
|
459
544
|
preferredRelayersEns?: string[];
|
|
460
545
|
}
|
|
461
|
-
interface TCPaymasterUnshieldOptions {
|
|
546
|
+
interface TCPaymasterUnshieldOptions extends UnshieldOptions {
|
|
462
547
|
mode: 'paymaster';
|
|
463
548
|
delegation?: DelegationConfig;
|
|
464
549
|
}
|
|
@@ -495,7 +580,7 @@ type RequireOnly<T, Keys extends keyof T> = Partial<T> & Pick<T, Keys>;
|
|
|
495
580
|
declare class TornadoCashProtocol implements TCInstance {
|
|
496
581
|
readonly host: Host;
|
|
497
582
|
private stateManager;
|
|
498
|
-
constructor(host: Host, { accountIndex, initialState, protocolConfig, artifactsLoader, stateManagerWorkerUrl, relayerConfig, paymasterConfig, relayerClientFactory, }: RequireOnly<TCProtocolParams, 'protocolConfig'>);
|
|
583
|
+
constructor(host: Host, { accountIndex, initialState, protocolConfig, artifactsLoader, stateManagerWorkerUrl, relayerConfig, paymasterConfig, relayerClientFactory, minExternalSyncBlocksAmount, }: RequireOnly<TCProtocolParams, 'protocolConfig'>);
|
|
499
584
|
instanceId: () => Promise<"0x1">;
|
|
500
585
|
/**
|
|
501
586
|
* Only process supported assets or error out?
|
|
@@ -510,6 +595,7 @@ declare class TornadoCashProtocol implements TCInstance {
|
|
|
510
595
|
*/
|
|
511
596
|
notes(assets?: ERC20AssetId[], includeSpent?: boolean): Promise<TCNote[]>;
|
|
512
597
|
prepareShield(assets: TCAssetAmount, options?: TCPrepareShieldOptions | `0x${string}`): Promise<TCPublicOperation>;
|
|
598
|
+
prepareUnshield(assets: AssetAmount, to: AccountId): Promise<TCPrivateOperation<'relayer'>>;
|
|
513
599
|
prepareUnshield(assets: AssetAmount, to: AccountId, options?: TCRelayerUnshieldOptions): Promise<TCPrivateOperation<'relayer'>>;
|
|
514
600
|
prepareUnshield(assets: AssetAmount, to: AccountId, options?: TCPaymasterUnshieldOptions): Promise<TCPrivateOperation<'paymaster'>>;
|
|
515
601
|
sync(): Promise<void>;
|
|
@@ -534,11 +620,11 @@ declare const TornadoPaymasterConfigs: {
|
|
|
534
620
|
readonly 11155111: {
|
|
535
621
|
readonly bundlerUrl: "https://public.pimlico.io/v2/11155111/rpc";
|
|
536
622
|
readonly entryPointAddress: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108";
|
|
537
|
-
readonly paymasterAddress: "
|
|
623
|
+
readonly paymasterAddress: "0x1c5aCCb9c09D72945b79EC986776136bE01d7B2F";
|
|
538
624
|
readonly poolsAccountsMap: {
|
|
539
|
-
readonly '0x8c4a04d872a6c1be37964a21ba3a138525dff50b': "
|
|
540
|
-
readonly '0x8cc930096b4df705a007c4a039bdfa1320ed2508': "
|
|
541
|
-
readonly '0x6921fd1a97441dd603a997ed6ddf388658daf754': "
|
|
625
|
+
readonly '0x8c4a04d872a6c1be37964a21ba3a138525dff50b': "0xa616aAE443FCCABfc2F1EA2Afe001E5046FFDCe0";
|
|
626
|
+
readonly '0x8cc930096b4df705a007c4a039bdfa1320ed2508': "0x67a898343F32641206d0f30CB3367944a8919A3A";
|
|
627
|
+
readonly '0x6921fd1a97441dd603a997ed6ddf388658daf754': "0xbF0a7969dacF8337716d0F283df0574dF56b0479";
|
|
542
628
|
};
|
|
543
629
|
};
|
|
544
630
|
readonly 1: never;
|
|
@@ -558,7 +644,6 @@ declare const TornadoCashConfigs: {
|
|
|
558
644
|
readonly address: 1329937909414098670091808248270266272594403334985n;
|
|
559
645
|
};
|
|
560
646
|
readonly weth: 1097077688018008265106216665536940668749033598146n;
|
|
561
|
-
readonly uniswapQuoterV2: 559478315000592720989748010348495519536007655966n;
|
|
562
647
|
};
|
|
563
648
|
readonly 11155111: {
|
|
564
649
|
readonly ensSubdomainKey: "sepolia-tornado";
|
|
@@ -574,7 +659,6 @@ declare const TornadoCashConfigs: {
|
|
|
574
659
|
readonly address: 368418168928372787409224158240737522620871644738n;
|
|
575
660
|
};
|
|
576
661
|
readonly weth: 1461358721292675304620367034492138750323989506836n;
|
|
577
|
-
readonly uniswapQuoterV2: 1353730886217084326490181093487957540173111046067n;
|
|
578
662
|
};
|
|
579
663
|
};
|
|
580
664
|
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createSelector, createAsyncThunk } from '@reduxjs/toolkit';
|
|
2
2
|
import { createTx } from '@kohaku-eth/provider';
|
|
3
|
-
import { encodeFunctionData, toHex, erc20Abi } from 'viem';
|
|
3
|
+
import { encodeFunctionData, toHex, erc20Abi, http } from 'viem';
|
|
4
4
|
import { proxy } from 'comlink';
|
|
5
5
|
import { loadStateManagerWorker } from '#worker-loader';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
6
|
+
import 'viem/accounts';
|
|
7
|
+
import { createBundlerClient } from 'viem/account-abstraction';
|
|
8
8
|
import { numberToBytesLE, bytesToNumberLE, concatBytes } from '@noble/curves/utils.js';
|
|
9
9
|
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
10
10
|
import { pedersenHash as pedersenHash$1, Point } from 'micro-zk-proofs/pedersen.js';
|
|
@@ -348,11 +348,12 @@ var TornadoPaymasterConfigs = {
|
|
|
348
348
|
11155111: {
|
|
349
349
|
bundlerUrl: "https://public.pimlico.io/v2/11155111/rpc",
|
|
350
350
|
entryPointAddress: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
|
|
351
|
-
paymasterAddress: "
|
|
351
|
+
paymasterAddress: "0x1c5aCCb9c09D72945b79EC986776136bE01d7B2F",
|
|
352
352
|
poolsAccountsMap: {
|
|
353
|
-
|
|
354
|
-
"
|
|
355
|
-
"
|
|
353
|
+
// pool -> per-pool TornadoFeeAdapter (eth_0_1, eth_1, dai_100)
|
|
354
|
+
"0x8c4a04d872a6c1be37964a21ba3a138525dff50b": "0xa616aAE443FCCABfc2F1EA2Afe001E5046FFDCe0",
|
|
355
|
+
"0x8cc930096b4df705a007c4a039bdfa1320ed2508": "0x67a898343F32641206d0f30CB3367944a8919A3A",
|
|
356
|
+
"0x6921fd1a97441dd603a997ed6ddf388658daf754": "0xbF0a7969dacF8337716d0F283df0574dF56b0479"
|
|
356
357
|
}
|
|
357
358
|
},
|
|
358
359
|
1: {}
|
|
@@ -371,8 +372,7 @@ var TornadoCashConfigs = {
|
|
|
371
372
|
aggregator: {
|
|
372
373
|
address: 0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49n
|
|
373
374
|
},
|
|
374
|
-
weth: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2n
|
|
375
|
-
uniswapQuoterV2: 0x61fFE014bA17989E743c5F6cB21bF9697530B21en
|
|
375
|
+
weth: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2n
|
|
376
376
|
},
|
|
377
377
|
11155111: {
|
|
378
378
|
ensSubdomainKey: "sepolia-tornado",
|
|
@@ -387,8 +387,7 @@ var TornadoCashConfigs = {
|
|
|
387
387
|
aggregator: {
|
|
388
388
|
address: 0x4088712AC9fad39ea133cdb9130E465d235e9642n
|
|
389
389
|
},
|
|
390
|
-
weth: 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14n
|
|
391
|
-
uniswapQuoterV2: 0xEd1f6473345F45b75F8179591dd5bA1888cf2FB3n
|
|
390
|
+
weth: 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14n
|
|
392
391
|
}
|
|
393
392
|
};
|
|
394
393
|
|
|
@@ -420,7 +419,8 @@ var TornadoCashProtocol = class {
|
|
|
420
419
|
stateManagerWorkerUrl,
|
|
421
420
|
relayerConfig,
|
|
422
421
|
paymasterConfig = TornadoPaymasterConfigs,
|
|
423
|
-
relayerClientFactory = () => new RelayerClient(host)
|
|
422
|
+
relayerClientFactory = () => new RelayerClient(host),
|
|
423
|
+
minExternalSyncBlocksAmount
|
|
424
424
|
}) {
|
|
425
425
|
this.host = host;
|
|
426
426
|
this.stateManager = (async () => {
|
|
@@ -431,6 +431,18 @@ var TornadoCashProtocol = class {
|
|
|
431
431
|
reject(err);
|
|
432
432
|
});
|
|
433
433
|
});
|
|
434
|
+
const { externalSyncProvider } = host;
|
|
435
|
+
const externalSyncClient = externalSyncProvider && {
|
|
436
|
+
getEvents: async (params) => {
|
|
437
|
+
const events = [];
|
|
438
|
+
for await (const event of externalSyncProvider.streamEvents(params)) {
|
|
439
|
+
events.push(event);
|
|
440
|
+
}
|
|
441
|
+
return events;
|
|
442
|
+
},
|
|
443
|
+
firstCoveredBlock: (params) => externalSyncProvider.firstCoveredBlock(params),
|
|
444
|
+
lastCoveredBlock: (params) => externalSyncProvider.lastCoveredBlock(params)
|
|
445
|
+
};
|
|
434
446
|
await Promise.race([
|
|
435
447
|
remote.init(
|
|
436
448
|
proxy(host.provider),
|
|
@@ -439,7 +451,8 @@ var TornadoCashProtocol = class {
|
|
|
439
451
|
proxy(host.storage),
|
|
440
452
|
proxy(initialState),
|
|
441
453
|
proxy(artifactsLoader),
|
|
442
|
-
|
|
454
|
+
externalSyncClient ? proxy(externalSyncClient) : void 0,
|
|
455
|
+
{ protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }
|
|
443
456
|
),
|
|
444
457
|
workerReady
|
|
445
458
|
]);
|
|
@@ -448,7 +461,16 @@ var TornadoCashProtocol = class {
|
|
|
448
461
|
getBalances: ((assets) => remote.getBalances(assets)),
|
|
449
462
|
getNotes: (params) => remote.getNotes(params),
|
|
450
463
|
getDepositPayload: (params) => remote.getDepositPayload(params),
|
|
451
|
-
getWithdrawalPayloads: (params) =>
|
|
464
|
+
getWithdrawalPayloads: (params) => {
|
|
465
|
+
if (params.mode === "paymaster") {
|
|
466
|
+
const { tailCalls, ...rest } = params;
|
|
467
|
+
return remote.getWithdrawalPayloads(
|
|
468
|
+
rest,
|
|
469
|
+
tailCalls ? proxy(tailCalls) : void 0
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
return remote.getWithdrawalPayloads(params);
|
|
473
|
+
},
|
|
452
474
|
dumpState: (() => remote.dumpState())
|
|
453
475
|
};
|
|
454
476
|
})();
|
|
@@ -515,7 +537,10 @@ var TornadoCashProtocol = class {
|
|
|
515
537
|
});
|
|
516
538
|
return { txns: tx };
|
|
517
539
|
}
|
|
518
|
-
async prepareUnshield(assets, to, options) {
|
|
540
|
+
async prepareUnshield(assets, to, options = { mode: "relayer" }) {
|
|
541
|
+
if (options.mode === "relayer" && options.tailCalls !== void 0) {
|
|
542
|
+
throw new Error("Tail Calls are only supported when using paymaster mode.");
|
|
543
|
+
}
|
|
519
544
|
const { asset, amount } = assets;
|
|
520
545
|
const parsedAsset = BigInt(asset.contract || E_ADDRESS_BIGINT);
|
|
521
546
|
const stateManager = await this.stateManager;
|
|
@@ -530,7 +555,8 @@ var TornadoCashProtocol = class {
|
|
|
530
555
|
withdrawals = await stateManager.getWithdrawalPayloads({
|
|
531
556
|
...baseParams,
|
|
532
557
|
mode: "paymaster",
|
|
533
|
-
delegation: options.delegation
|
|
558
|
+
delegation: options.delegation,
|
|
559
|
+
tailCalls: options.tailCalls
|
|
534
560
|
});
|
|
535
561
|
} else {
|
|
536
562
|
withdrawals = await stateManager.getWithdrawalPayloads({
|
|
@@ -553,120 +579,51 @@ var TornadoCashProtocol = class {
|
|
|
553
579
|
return stateManager.dumpState();
|
|
554
580
|
}
|
|
555
581
|
};
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
var ERC20_TRANSFER_GAS = 100000n;
|
|
559
|
-
var baseGasUnits = {
|
|
560
|
-
preVerificationGas: 80000n,
|
|
561
|
-
verificationGasLimit: 50000n,
|
|
562
|
-
callGasLimit: 300000n,
|
|
563
|
-
paymasterVerificationGasLimit: 350000n,
|
|
564
|
-
paymasterPostOpGasLimit: 10000n
|
|
565
|
-
};
|
|
566
|
-
function reasonableGasUnits(isERC20) {
|
|
567
|
-
if (!isERC20) return baseGasUnits;
|
|
568
|
-
return {
|
|
569
|
-
...baseGasUnits,
|
|
570
|
-
callGasLimit: baseGasUnits.callGasLimit + ERC20_TRANSFER_GAS
|
|
571
|
-
};
|
|
582
|
+
function createPaymasterBundlerClient(bundlerUrl) {
|
|
583
|
+
return createBundlerClient({ transport: http(bundlerUrl) });
|
|
572
584
|
}
|
|
573
|
-
async function
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
nonce
|
|
578
|
-
}) {
|
|
579
|
-
const account = privateKeyToAccount(privateKey);
|
|
580
|
-
const authorization = await account.signAuthorization({
|
|
581
|
-
contractAddress: accountAddress,
|
|
582
|
-
chainId,
|
|
583
|
-
nonce
|
|
585
|
+
async function sendSerializedUserOperation(client, op, entryPoint) {
|
|
586
|
+
return client.request({
|
|
587
|
+
method: "eth_sendUserOperation",
|
|
588
|
+
params: [op, entryPoint]
|
|
584
589
|
});
|
|
585
|
-
return { authorization, senderAddress: account.address };
|
|
586
590
|
}
|
|
587
591
|
|
|
588
592
|
// src/paymaster/paymaster-broadcaster.ts
|
|
589
593
|
var PaymasterBroadcaster = class _PaymasterBroadcaster {
|
|
590
|
-
constructor(provider, options) {
|
|
591
|
-
this.provider = provider;
|
|
592
|
-
this.options = options;
|
|
593
|
-
}
|
|
594
|
-
provider;
|
|
595
|
-
options;
|
|
596
594
|
async broadcast(withdrawals) {
|
|
597
|
-
const
|
|
598
|
-
const {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
])
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
595
|
+
const bySender = /* @__PURE__ */ new Map();
|
|
596
|
+
for (const w of withdrawals) {
|
|
597
|
+
const key = w.userOperation.sender.toLowerCase();
|
|
598
|
+
const group = bySender.get(key) ?? [];
|
|
599
|
+
group.push(w);
|
|
600
|
+
bySender.set(key, group);
|
|
601
|
+
}
|
|
602
|
+
const groupResults = await Promise.allSettled(
|
|
603
|
+
[...bySender.values()].map(async (group) => {
|
|
604
|
+
const out = [];
|
|
605
|
+
for (const w of group) {
|
|
606
|
+
out.push(await _PaymasterBroadcaster.broadcastOne(w));
|
|
607
|
+
}
|
|
608
|
+
return out;
|
|
609
|
+
})
|
|
612
610
|
);
|
|
613
|
-
const failed =
|
|
611
|
+
const failed = groupResults.filter((r) => r.status === "rejected");
|
|
614
612
|
if (failed.length > 0) {
|
|
615
613
|
console.warn(
|
|
616
614
|
`Some paymaster withdrawals failed.`,
|
|
617
615
|
failed.map((e) => e.reason).join("\n")
|
|
618
616
|
);
|
|
619
617
|
}
|
|
620
|
-
return
|
|
618
|
+
return groupResults.filter((r) => r.status === "fulfilled").flatMap((r) => r.value);
|
|
621
619
|
}
|
|
622
|
-
static async broadcastOne(withdrawal
|
|
623
|
-
const {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
bundlerUrl,
|
|
628
|
-
accountAddress,
|
|
629
|
-
isERC20
|
|
630
|
-
} = withdrawal;
|
|
631
|
-
const [root, nullifierHash, recipient, _paymasterAddress, feeHex] = proofArgs;
|
|
632
|
-
if (BigInt(paymasterAddress) !== BigInt(_paymasterAddress)) {
|
|
633
|
-
throw new Error(`relayer must be paymaster when using the 4337 paymaster flow: ${paymasterAddress} != ${_paymasterAddress}`);
|
|
634
|
-
}
|
|
635
|
-
const delegation = withdrawal.delegation ?? await _PaymasterBroadcaster.generateRandomDelegation(accountAddress, provider);
|
|
636
|
-
const { senderAddress, authorization } = delegation;
|
|
637
|
-
const bundlerClient = new BundlerClient(bundlerUrl, entryPointAddress);
|
|
638
|
-
const { standard: { maxFeePerGas, maxPriorityFeePerGas } } = await bundlerClient.getUserOperationGasPrice();
|
|
639
|
-
let gas;
|
|
640
|
-
{
|
|
641
|
-
gas = {
|
|
642
|
-
type: "manual",
|
|
643
|
-
...reasonableGasUnits(isERC20),
|
|
644
|
-
maxFeePerGas,
|
|
645
|
-
maxPriorityFeePerGas
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
const op = await new TornadoBuilder(senderAddress).withPaymaster(paymasterAddress).withAuthorization(authorization).withWithdraw(
|
|
649
|
-
proofHex,
|
|
650
|
-
root,
|
|
651
|
-
nullifierHash,
|
|
652
|
-
recipient,
|
|
653
|
-
_paymasterAddress,
|
|
654
|
-
BigInt(feeHex)
|
|
655
|
-
).withGas(gas).build(provider, bundlerClient);
|
|
656
|
-
const userOpHash = await bundlerClient.sendUserOperation(op);
|
|
657
|
-
await bundlerClient.waitForUserOperationReceipt(userOpHash);
|
|
620
|
+
static async broadcastOne(withdrawal) {
|
|
621
|
+
const { bundlerUrl, entryPointAddress, userOperation } = withdrawal;
|
|
622
|
+
const bundlerClient = createPaymasterBundlerClient(bundlerUrl);
|
|
623
|
+
const userOpHash = await sendSerializedUserOperation(bundlerClient, userOperation, entryPointAddress);
|
|
624
|
+
await bundlerClient.waitForUserOperationReceipt({ hash: userOpHash });
|
|
658
625
|
return { userOpHash };
|
|
659
626
|
}
|
|
660
|
-
static async generateRandomDelegation(accountAddress, provider) {
|
|
661
|
-
const privateKey = generatePrivateKey();
|
|
662
|
-
const chainId = Number(await provider.getChainId());
|
|
663
|
-
return signDelegationAuthorization({
|
|
664
|
-
privateKey,
|
|
665
|
-
accountAddress,
|
|
666
|
-
chainId,
|
|
667
|
-
nonce: 0
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
627
|
};
|
|
671
628
|
|
|
672
629
|
// src/plugin/broadcaster.ts
|
|
@@ -678,7 +635,7 @@ var TornadoCashBroadcaster = class {
|
|
|
678
635
|
host,
|
|
679
636
|
relayerClientFactory = () => new RelayerClient({ network: host.network }),
|
|
680
637
|
paymasterConfig,
|
|
681
|
-
paymasterClientFactory = () => new PaymasterBroadcaster(
|
|
638
|
+
paymasterClientFactory = () => new PaymasterBroadcaster()
|
|
682
639
|
}) {
|
|
683
640
|
this.provider = host.provider;
|
|
684
641
|
this.relayerClient = relayerClientFactory();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/utils/merkle-tree/merkle-tree.util.browser.ts
|
|
2
|
-
import { generateMimcMerkleProof, createMimcMerkleTreeParallel } from "mimc-tree";
|
|
2
|
+
import { generateMimcMerkleProof, createMimcMerkleTreeParallel } from "@kohaku-eth/mimc-tree";
|
|
3
3
|
var buildTree = async (leaves) => {
|
|
4
4
|
return createMimcMerkleTreeParallel(leaves, { workerUrl: "./merkle-tree-worker.browser.js" });
|
|
5
5
|
};
|
package/dist/merkle-tree.node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/utils/merkle-tree/merkle-tree.util.node.ts
|
|
2
|
-
import { generateMimcMerkleProof, createMimcMerkleTreeNodejsParallel } from "mimc-tree";
|
|
2
|
+
import { generateMimcMerkleProof, createMimcMerkleTreeNodejsParallel } from "@kohaku-eth/mimc-tree";
|
|
3
3
|
var buildTree = async (leaves) => {
|
|
4
4
|
return createMimcMerkleTreeNodejsParallel(leaves);
|
|
5
5
|
};
|