@kohaku-eth/tornado-cash 0.0.2-alpha.12 → 0.0.2-alpha.13
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 +93 -18
- package/dist/index.js +70 -114
- package/dist/state-manager.worker.js +17031 -17990
- package/dist/state-manager.worker.node.js +16216 -17175
- package/dist/worker-loader.browser.d.ts +53 -8
- package/dist/worker-loader.node.d.ts +53 -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,38 @@ 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>;
|
|
253
292
|
}
|
|
254
293
|
|
|
255
294
|
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 +328,7 @@ interface IRelayerFeeConfig {
|
|
|
289
328
|
interface StoreFactoryParams {
|
|
290
329
|
secretManagerFactory: () => Promise<ISecretManager>;
|
|
291
330
|
dataService: IDataService;
|
|
331
|
+
syncService: ISyncService;
|
|
292
332
|
relayerClient: IRelayerClient;
|
|
293
333
|
paymasterConfig: IChainsPaymastersConfig;
|
|
294
334
|
storageToSyncTo?: Storage;
|
|
@@ -303,6 +343,36 @@ declare enum DepositStrategy {
|
|
|
303
343
|
MinFee = 1
|
|
304
344
|
}
|
|
305
345
|
|
|
346
|
+
interface SerializedAuth {
|
|
347
|
+
address: Address$1;
|
|
348
|
+
chainId: Hex;
|
|
349
|
+
nonce: Hex;
|
|
350
|
+
r: Hex;
|
|
351
|
+
s: Hex;
|
|
352
|
+
yParity: Hex;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* A userOp serialized to the hex shape expected by `eth_sendUserOperation`, so
|
|
356
|
+
* it can be carried as plain (JSON-serializable) data from the prepare phase
|
|
357
|
+
* (thunk) to the broadcast phase.
|
|
358
|
+
*/
|
|
359
|
+
interface SerializedUserOperation {
|
|
360
|
+
sender: `0x${string}`;
|
|
361
|
+
nonce: `0x${string}`;
|
|
362
|
+
callData: `0x${string}`;
|
|
363
|
+
callGasLimit: `0x${string}`;
|
|
364
|
+
verificationGasLimit: `0x${string}`;
|
|
365
|
+
preVerificationGas: `0x${string}`;
|
|
366
|
+
maxFeePerGas: `0x${string}`;
|
|
367
|
+
maxPriorityFeePerGas: `0x${string}`;
|
|
368
|
+
paymaster?: `0x${string}`;
|
|
369
|
+
paymasterVerificationGasLimit?: `0x${string}`;
|
|
370
|
+
paymasterPostOpGasLimit?: `0x${string}`;
|
|
371
|
+
paymasterData?: `0x${string}`;
|
|
372
|
+
signature: `0x${string}`;
|
|
373
|
+
eip7702Auth?: SerializedAuth;
|
|
374
|
+
}
|
|
375
|
+
|
|
306
376
|
interface SignedDelegation {
|
|
307
377
|
senderAddress: `0x${string}`;
|
|
308
378
|
authorization: SignedAuthorization;
|
|
@@ -322,8 +392,7 @@ interface IGenericPaymasterWithdrawalPayload {
|
|
|
322
392
|
paymasterAddress: `0x${string}`;
|
|
323
393
|
entryPointAddress: `0x${string}`;
|
|
324
394
|
bundlerUrl: string;
|
|
325
|
-
|
|
326
|
-
delegation?: SignedDelegation;
|
|
395
|
+
userOperation: SerializedUserOperation;
|
|
327
396
|
}
|
|
328
397
|
interface PaymasterBroadcastResult {
|
|
329
398
|
userOpHash: Hash;
|
|
@@ -377,6 +446,12 @@ interface TCProtocolParams {
|
|
|
377
446
|
artifactsLoader?: () => Promise<ITornadoArtifacts>;
|
|
378
447
|
initialState?: () => Promise<Record<string, PublicRootState>>;
|
|
379
448
|
stateManagerWorkerUrl?: string;
|
|
449
|
+
/**
|
|
450
|
+
* When a pool is at least this many blocks behind, use the host's
|
|
451
|
+
* `externalSyncProvider` (if any) for the bulk of the sync instead of the
|
|
452
|
+
* chain. Omit to always sync from the chain.
|
|
453
|
+
*/
|
|
454
|
+
minExternalSyncBlocksAmount?: number;
|
|
380
455
|
}
|
|
381
456
|
interface IBaseOperationParams {
|
|
382
457
|
}
|
|
@@ -396,6 +471,7 @@ interface IRelayerWithdrawParams extends IWithdrawBaseParams {
|
|
|
396
471
|
interface IPaymasterWithdrawParams extends IWithdrawBaseParams {
|
|
397
472
|
mode: 'paymaster';
|
|
398
473
|
delegation?: DelegationConfig;
|
|
474
|
+
tailCalls?: (address: AccountId) => Promise<TxData[]>;
|
|
399
475
|
}
|
|
400
476
|
type IWithdrawapOperationParams = IRelayerWithdrawParams | IPaymasterWithdrawParams;
|
|
401
477
|
interface IGetNotesParams extends IBaseOperationParams {
|
|
@@ -445,7 +521,7 @@ type TCBroadcaster = Broadcaster<TCPrivateOperation, ITornadoWithdrawResponse[]>
|
|
|
445
521
|
interface TCBaseCredential {
|
|
446
522
|
accountIndex: number;
|
|
447
523
|
}
|
|
448
|
-
interface TCPluginParameters extends TCBroadcasterParameters, TCBaseCredential, Pick<TCProtocolParams, 'initialState'> {
|
|
524
|
+
interface TCPluginParameters extends TCBroadcasterParameters, TCBaseCredential, Pick<TCProtocolParams, 'initialState' | 'minExternalSyncBlocksAmount'> {
|
|
449
525
|
protocolConfig: TCProtocolConfig;
|
|
450
526
|
relayerConfig?: IRelayerFeeConfig;
|
|
451
527
|
stateManagerWorkerUrl?: string;
|
|
@@ -454,11 +530,11 @@ interface TCPluginParameters extends TCBroadcasterParameters, TCBaseCredential,
|
|
|
454
530
|
type TCAddress = Address$1;
|
|
455
531
|
type TCAssetAmount<Tag extends string | undefined = undefined> = AssetAmount<ERC20AssetId, bigint, Tag>;
|
|
456
532
|
type TCAssetBalance = TCAssetAmount;
|
|
457
|
-
interface TCRelayerUnshieldOptions {
|
|
533
|
+
interface TCRelayerUnshieldOptions extends UnshieldOptions {
|
|
458
534
|
mode: 'relayer';
|
|
459
535
|
preferredRelayersEns?: string[];
|
|
460
536
|
}
|
|
461
|
-
interface TCPaymasterUnshieldOptions {
|
|
537
|
+
interface TCPaymasterUnshieldOptions extends UnshieldOptions {
|
|
462
538
|
mode: 'paymaster';
|
|
463
539
|
delegation?: DelegationConfig;
|
|
464
540
|
}
|
|
@@ -495,7 +571,7 @@ type RequireOnly<T, Keys extends keyof T> = Partial<T> & Pick<T, Keys>;
|
|
|
495
571
|
declare class TornadoCashProtocol implements TCInstance {
|
|
496
572
|
readonly host: Host;
|
|
497
573
|
private stateManager;
|
|
498
|
-
constructor(host: Host, { accountIndex, initialState, protocolConfig, artifactsLoader, stateManagerWorkerUrl, relayerConfig, paymasterConfig, relayerClientFactory, }: RequireOnly<TCProtocolParams, 'protocolConfig'>);
|
|
574
|
+
constructor(host: Host, { accountIndex, initialState, protocolConfig, artifactsLoader, stateManagerWorkerUrl, relayerConfig, paymasterConfig, relayerClientFactory, minExternalSyncBlocksAmount, }: RequireOnly<TCProtocolParams, 'protocolConfig'>);
|
|
499
575
|
instanceId: () => Promise<"0x1">;
|
|
500
576
|
/**
|
|
501
577
|
* Only process supported assets or error out?
|
|
@@ -510,6 +586,7 @@ declare class TornadoCashProtocol implements TCInstance {
|
|
|
510
586
|
*/
|
|
511
587
|
notes(assets?: ERC20AssetId[], includeSpent?: boolean): Promise<TCNote[]>;
|
|
512
588
|
prepareShield(assets: TCAssetAmount, options?: TCPrepareShieldOptions | `0x${string}`): Promise<TCPublicOperation>;
|
|
589
|
+
prepareUnshield(assets: AssetAmount, to: AccountId): Promise<TCPrivateOperation<'relayer'>>;
|
|
513
590
|
prepareUnshield(assets: AssetAmount, to: AccountId, options?: TCRelayerUnshieldOptions): Promise<TCPrivateOperation<'relayer'>>;
|
|
514
591
|
prepareUnshield(assets: AssetAmount, to: AccountId, options?: TCPaymasterUnshieldOptions): Promise<TCPrivateOperation<'paymaster'>>;
|
|
515
592
|
sync(): Promise<void>;
|
|
@@ -534,11 +611,11 @@ declare const TornadoPaymasterConfigs: {
|
|
|
534
611
|
readonly 11155111: {
|
|
535
612
|
readonly bundlerUrl: "https://public.pimlico.io/v2/11155111/rpc";
|
|
536
613
|
readonly entryPointAddress: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108";
|
|
537
|
-
readonly paymasterAddress: "
|
|
614
|
+
readonly paymasterAddress: "0x1c5aCCb9c09D72945b79EC986776136bE01d7B2F";
|
|
538
615
|
readonly poolsAccountsMap: {
|
|
539
|
-
readonly '0x8c4a04d872a6c1be37964a21ba3a138525dff50b': "
|
|
540
|
-
readonly '0x8cc930096b4df705a007c4a039bdfa1320ed2508': "
|
|
541
|
-
readonly '0x6921fd1a97441dd603a997ed6ddf388658daf754': "
|
|
616
|
+
readonly '0x8c4a04d872a6c1be37964a21ba3a138525dff50b': "0xa616aAE443FCCABfc2F1EA2Afe001E5046FFDCe0";
|
|
617
|
+
readonly '0x8cc930096b4df705a007c4a039bdfa1320ed2508': "0x67a898343F32641206d0f30CB3367944a8919A3A";
|
|
618
|
+
readonly '0x6921fd1a97441dd603a997ed6ddf388658daf754': "0xbF0a7969dacF8337716d0F283df0574dF56b0479";
|
|
542
619
|
};
|
|
543
620
|
};
|
|
544
621
|
readonly 1: never;
|
|
@@ -558,7 +635,6 @@ declare const TornadoCashConfigs: {
|
|
|
558
635
|
readonly address: 1329937909414098670091808248270266272594403334985n;
|
|
559
636
|
};
|
|
560
637
|
readonly weth: 1097077688018008265106216665536940668749033598146n;
|
|
561
|
-
readonly uniswapQuoterV2: 559478315000592720989748010348495519536007655966n;
|
|
562
638
|
};
|
|
563
639
|
readonly 11155111: {
|
|
564
640
|
readonly ensSubdomainKey: "sepolia-tornado";
|
|
@@ -574,7 +650,6 @@ declare const TornadoCashConfigs: {
|
|
|
574
650
|
readonly address: 368418168928372787409224158240737522620871644738n;
|
|
575
651
|
};
|
|
576
652
|
readonly weth: 1461358721292675304620367034492138750323989506836n;
|
|
577
|
-
readonly uniswapQuoterV2: 1353730886217084326490181093487957540173111046067n;
|
|
578
653
|
};
|
|
579
654
|
};
|
|
580
655
|
|
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,17 @@ 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
|
+
lastCoveredBlock: (params) => externalSyncProvider.lastCoveredBlock(params)
|
|
444
|
+
};
|
|
434
445
|
await Promise.race([
|
|
435
446
|
remote.init(
|
|
436
447
|
proxy(host.provider),
|
|
@@ -439,7 +450,8 @@ var TornadoCashProtocol = class {
|
|
|
439
450
|
proxy(host.storage),
|
|
440
451
|
proxy(initialState),
|
|
441
452
|
proxy(artifactsLoader),
|
|
442
|
-
|
|
453
|
+
externalSyncClient ? proxy(externalSyncClient) : void 0,
|
|
454
|
+
{ protocolConfig, accountIndex, relayerConfig, paymasterConfig, minExternalSyncBlocksAmount }
|
|
443
455
|
),
|
|
444
456
|
workerReady
|
|
445
457
|
]);
|
|
@@ -448,7 +460,16 @@ var TornadoCashProtocol = class {
|
|
|
448
460
|
getBalances: ((assets) => remote.getBalances(assets)),
|
|
449
461
|
getNotes: (params) => remote.getNotes(params),
|
|
450
462
|
getDepositPayload: (params) => remote.getDepositPayload(params),
|
|
451
|
-
getWithdrawalPayloads: (params) =>
|
|
463
|
+
getWithdrawalPayloads: (params) => {
|
|
464
|
+
if (params.mode === "paymaster") {
|
|
465
|
+
const { tailCalls, ...rest } = params;
|
|
466
|
+
return remote.getWithdrawalPayloads(
|
|
467
|
+
rest,
|
|
468
|
+
tailCalls ? proxy(tailCalls) : void 0
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
return remote.getWithdrawalPayloads(params);
|
|
472
|
+
},
|
|
452
473
|
dumpState: (() => remote.dumpState())
|
|
453
474
|
};
|
|
454
475
|
})();
|
|
@@ -515,7 +536,10 @@ var TornadoCashProtocol = class {
|
|
|
515
536
|
});
|
|
516
537
|
return { txns: tx };
|
|
517
538
|
}
|
|
518
|
-
async prepareUnshield(assets, to, options) {
|
|
539
|
+
async prepareUnshield(assets, to, options = { mode: "relayer" }) {
|
|
540
|
+
if (options.mode === "relayer" && options.tailCalls !== void 0) {
|
|
541
|
+
throw new Error("Tail Calls are only supported when using paymaster mode.");
|
|
542
|
+
}
|
|
519
543
|
const { asset, amount } = assets;
|
|
520
544
|
const parsedAsset = BigInt(asset.contract || E_ADDRESS_BIGINT);
|
|
521
545
|
const stateManager = await this.stateManager;
|
|
@@ -530,7 +554,8 @@ var TornadoCashProtocol = class {
|
|
|
530
554
|
withdrawals = await stateManager.getWithdrawalPayloads({
|
|
531
555
|
...baseParams,
|
|
532
556
|
mode: "paymaster",
|
|
533
|
-
delegation: options.delegation
|
|
557
|
+
delegation: options.delegation,
|
|
558
|
+
tailCalls: options.tailCalls
|
|
534
559
|
});
|
|
535
560
|
} else {
|
|
536
561
|
withdrawals = await stateManager.getWithdrawalPayloads({
|
|
@@ -553,120 +578,51 @@ var TornadoCashProtocol = class {
|
|
|
553
578
|
return stateManager.dumpState();
|
|
554
579
|
}
|
|
555
580
|
};
|
|
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
|
-
};
|
|
581
|
+
function createPaymasterBundlerClient(bundlerUrl) {
|
|
582
|
+
return createBundlerClient({ transport: http(bundlerUrl) });
|
|
572
583
|
}
|
|
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
|
|
584
|
+
async function sendSerializedUserOperation(client, op, entryPoint) {
|
|
585
|
+
return client.request({
|
|
586
|
+
method: "eth_sendUserOperation",
|
|
587
|
+
params: [op, entryPoint]
|
|
584
588
|
});
|
|
585
|
-
return { authorization, senderAddress: account.address };
|
|
586
589
|
}
|
|
587
590
|
|
|
588
591
|
// src/paymaster/paymaster-broadcaster.ts
|
|
589
592
|
var PaymasterBroadcaster = class _PaymasterBroadcaster {
|
|
590
|
-
constructor(provider, options) {
|
|
591
|
-
this.provider = provider;
|
|
592
|
-
this.options = options;
|
|
593
|
-
}
|
|
594
|
-
provider;
|
|
595
|
-
options;
|
|
596
593
|
async broadcast(withdrawals) {
|
|
597
|
-
const
|
|
598
|
-
const {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
])
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
594
|
+
const bySender = /* @__PURE__ */ new Map();
|
|
595
|
+
for (const w of withdrawals) {
|
|
596
|
+
const key = w.userOperation.sender.toLowerCase();
|
|
597
|
+
const group = bySender.get(key) ?? [];
|
|
598
|
+
group.push(w);
|
|
599
|
+
bySender.set(key, group);
|
|
600
|
+
}
|
|
601
|
+
const groupResults = await Promise.allSettled(
|
|
602
|
+
[...bySender.values()].map(async (group) => {
|
|
603
|
+
const out = [];
|
|
604
|
+
for (const w of group) {
|
|
605
|
+
out.push(await _PaymasterBroadcaster.broadcastOne(w));
|
|
606
|
+
}
|
|
607
|
+
return out;
|
|
608
|
+
})
|
|
612
609
|
);
|
|
613
|
-
const failed =
|
|
610
|
+
const failed = groupResults.filter((r) => r.status === "rejected");
|
|
614
611
|
if (failed.length > 0) {
|
|
615
612
|
console.warn(
|
|
616
613
|
`Some paymaster withdrawals failed.`,
|
|
617
614
|
failed.map((e) => e.reason).join("\n")
|
|
618
615
|
);
|
|
619
616
|
}
|
|
620
|
-
return
|
|
617
|
+
return groupResults.filter((r) => r.status === "fulfilled").flatMap((r) => r.value);
|
|
621
618
|
}
|
|
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);
|
|
619
|
+
static async broadcastOne(withdrawal) {
|
|
620
|
+
const { bundlerUrl, entryPointAddress, userOperation } = withdrawal;
|
|
621
|
+
const bundlerClient = createPaymasterBundlerClient(bundlerUrl);
|
|
622
|
+
const userOpHash = await sendSerializedUserOperation(bundlerClient, userOperation, entryPointAddress);
|
|
623
|
+
await bundlerClient.waitForUserOperationReceipt({ hash: userOpHash });
|
|
658
624
|
return { userOpHash };
|
|
659
625
|
}
|
|
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
626
|
};
|
|
671
627
|
|
|
672
628
|
// src/plugin/broadcaster.ts
|
|
@@ -678,7 +634,7 @@ var TornadoCashBroadcaster = class {
|
|
|
678
634
|
host,
|
|
679
635
|
relayerClientFactory = () => new RelayerClient({ network: host.network }),
|
|
680
636
|
paymasterConfig,
|
|
681
|
-
paymasterClientFactory = () => new PaymasterBroadcaster(
|
|
637
|
+
paymasterClientFactory = () => new PaymasterBroadcaster()
|
|
682
638
|
}) {
|
|
683
639
|
this.provider = host.provider;
|
|
684
640
|
this.relayerClient = relayerClientFactory();
|