@morpho-org/bundler-sdk-viem 2.3.0-next.0 → 3.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/actions.d.ts CHANGED
@@ -5,7 +5,6 @@ import type { Action, ActionBundle, BundlerOperation, TransactionRequirement } f
5
5
  export declare const APPROVE_ONLY_ONCE_TOKENS: Partial<Record<ChainId, Address[]>>;
6
6
  export declare const encodeOperation: (operation: BundlerOperation, dataBefore: MaybeDraft<SimulationState>, supportsSignature?: boolean, index?: number) => {
7
7
  dataAfter: MaybeDraft<SimulationState>;
8
- value: bigint;
9
8
  actions: Action[];
10
9
  requirements: {
11
10
  signatures: import("./types/actions.js").SignatureRequirement[];
package/lib/actions.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import { encodeFunctionData, erc20Abi, maxUint256, verifyTypedData, zeroAddress, } from "viem";
2
- import { ChainId, MathLib, NATIVE_ADDRESS, convexWrapperTokens, erc20WrapperTokens, getChainAddresses, } from "@morpho-org/blue-sdk";
2
+ import { ChainId, MathLib, NATIVE_ADDRESS, convexWrapperTokens, erc20WrapperTokens, getChainAddresses, getUnwrappedToken, } from "@morpho-org/blue-sdk";
3
3
  import { Time, getValue } from "@morpho-org/morpho-ts";
4
4
  import { simulateOperation, } from "@morpho-org/simulation-sdk";
5
5
  import { blueAbi, getAuthorizationTypedData, getDaiPermitTypedData, getPermit2PermitTypedData, getPermitTypedData, } from "@morpho-org/blue-sdk-viem";
6
6
  import { signTypedData } from "viem/actions";
7
7
  import BundlerAction from "./BundlerAction.js";
8
- import { baseBundlerAbi } from "./abis.js";
9
8
  export const APPROVE_ONLY_ONCE_TOKENS = {
10
9
  [ChainId.EthMainnet]: [
11
10
  "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
@@ -19,14 +18,14 @@ const MAX_TOKEN_APPROVALS = {
19
18
  };
20
19
  const encodeErc20Approval = (token, sender, spender, amount, data) => {
21
20
  const { chainId } = data;
22
- const { morpho, bundler, permit2 } = getChainAddresses(chainId);
21
+ const { morpho, bundler3: { generalAdapter1 }, permit2, } = getChainAddresses(chainId);
23
22
  amount = MathLib.min(amount, MAX_TOKEN_APPROVALS[chainId]?.[token] ?? maxUint256);
24
23
  const txRequirements = [];
25
24
  if (APPROVE_ONLY_ONCE_TOKENS[chainId]?.includes(token)) {
26
25
  const contract = spender === morpho
27
26
  ? "morpho"
28
- : spender === bundler
29
- ? "bundler"
27
+ : spender === generalAdapter1
28
+ ? "bundler3.generalAdapter1"
30
29
  : spender === permit2
31
30
  ? "permit2"
32
31
  : undefined;
@@ -66,8 +65,7 @@ const encodeErc20Approval = (token, sender, spender, amount, data) => {
66
65
  export const encodeOperation = (operation, dataBefore, supportsSignature = true, index = 0) => {
67
66
  const { chainId } = dataBefore;
68
67
  const deadline = Time.timestamp() + Time.s.from.h(24n);
69
- const { morpho, bundler, permit2, publicAllocator, wNative, dai, wstEth, stEth, } = getChainAddresses(chainId);
70
- let value = 0n;
68
+ const { morpho, bundler3: { bundler3, generalAdapter1 }, permit2, wNative, dai, wstEth, stEth, } = getChainAddresses(chainId);
71
69
  const actions = [];
72
70
  const requirements = {
73
71
  signatures: [],
@@ -101,7 +99,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
101
99
  const ownerData = dataBefore.getUser(owner);
102
100
  const authorization = {
103
101
  authorizer: owner,
104
- authorized: bundler,
102
+ authorized: generalAdapter1,
105
103
  isAuthorized: true,
106
104
  deadline,
107
105
  nonce: ownerData.morphoNonce,
@@ -114,10 +112,11 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
114
112
  requirements.signatures.push({
115
113
  action,
116
114
  async sign(client, account = client.account) {
117
- if (action.args[1] != null)
118
- return action.args[1];
115
+ let signature = action.args[1];
116
+ if (signature != null)
117
+ return signature;
119
118
  const typedData = getAuthorizationTypedData(authorization, chainId);
120
- const signature = await signTypedData(client, {
119
+ signature = await signTypedData(client, {
121
120
  ...typedData,
122
121
  account,
123
122
  });
@@ -134,13 +133,13 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
134
133
  // Signatures are not supported, fallback to standard approval.
135
134
  requirements.txs.push({
136
135
  type: "morphoSetAuthorization",
137
- args: [bundler, true],
136
+ args: [generalAdapter1, true],
138
137
  tx: {
139
138
  to: morpho,
140
139
  data: encodeFunctionData({
141
140
  abi: blueAbi,
142
141
  functionName: "setAuthorization",
143
- args: [bundler, true],
142
+ args: [generalAdapter1, true],
144
143
  }),
145
144
  },
146
145
  });
@@ -166,20 +165,20 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
166
165
  const action = address === dai
167
166
  ? {
168
167
  type: "permitDai",
169
- args: [nonce, deadline, true, null],
168
+ args: [sender, nonce, deadline, true, null, spender],
170
169
  }
171
170
  : {
172
171
  type: "permit",
173
- args: [address, amount, deadline, null],
172
+ args: [sender, address, amount, deadline, null, spender],
174
173
  };
175
174
  actions.push(action);
176
175
  const tokenData = dataBefore.getToken(address);
177
176
  requirements.signatures.push({
178
177
  action,
179
178
  async sign(client, account = client.account) {
180
- if (action.args[3] != null)
181
- return action.args[3]; // action is already signed
182
- let signature;
179
+ let signature = action.args[4];
180
+ if (signature != null)
181
+ return signature; // action is already signed
183
182
  if (address === dai) {
184
183
  const typedData = getDaiPermitTypedData({
185
184
  owner: sender,
@@ -217,7 +216,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
217
216
  signature,
218
217
  });
219
218
  }
220
- return (action.args[3] = signature);
219
+ return (action.args[4] = signature);
221
220
  },
222
221
  });
223
222
  break;
@@ -235,6 +234,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
235
234
  const action = {
236
235
  type: "approve2",
237
236
  args: [
237
+ sender,
238
238
  {
239
239
  details: {
240
240
  token: address,
@@ -242,7 +242,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
242
242
  nonce: Number(nonce),
243
243
  expiration: Number(expiration),
244
244
  },
245
- spender: bundler,
245
+ spender: bundler3,
246
246
  sigDeadline: deadline,
247
247
  },
248
248
  null,
@@ -252,9 +252,10 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
252
252
  requirements.signatures.push({
253
253
  action,
254
254
  async sign(client, account = client.account) {
255
- const { details, spender, sigDeadline } = action.args[0];
256
- if (action.args[1] != null)
257
- return action.args[1]; // action is already signed
255
+ const { details, spender, sigDeadline } = action.args[1];
256
+ let signature = action.args[2];
257
+ if (signature != null)
258
+ return signature; // action is already signed
258
259
  const typedData = getPermit2PermitTypedData({
259
260
  spender,
260
261
  allowance: details.amount,
@@ -263,7 +264,7 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
263
264
  deadline: sigDeadline,
264
265
  expiration: details.expiration,
265
266
  }, chainId);
266
- const signature = await signTypedData(client, {
267
+ signature = await signTypedData(client, {
267
268
  ...typedData,
268
269
  account,
269
270
  });
@@ -272,87 +273,52 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
272
273
  address: sender, // Verify against the permit's owner.
273
274
  signature,
274
275
  });
275
- return (action.args[1] = signature);
276
+ return (action.args[2] = signature);
276
277
  },
277
278
  });
278
279
  break;
279
280
  }
280
281
  // Signatures are not supported, fallback to standard approval.
281
- requirements.txs.push(...encodeErc20Approval(address, sender, bundler, amount, dataBefore));
282
+ requirements.txs.push(...encodeErc20Approval(address, sender, generalAdapter1, amount, dataBefore));
282
283
  break;
283
284
  }
284
285
  case "Erc20_Transfer": {
285
286
  const { amount, from, to } = operation.args;
286
- // Output transfer from the bundler.
287
- if (from === bundler) {
288
- if (address === NATIVE_ADDRESS) {
289
- actions.push({
290
- type: "nativeTransfer",
291
- args: [to, amount],
292
- });
293
- break;
294
- }
287
+ if (address === NATIVE_ADDRESS) {
295
288
  actions.push({
296
- type: "erc20Transfer",
297
- args: [address, to, amount],
289
+ type: "nativeTransfer",
290
+ args: [from, to, amount],
298
291
  });
299
292
  break;
300
293
  }
301
- // Input transfer to the bundler.
302
- if (to === bundler) {
303
- // Native token transfer is added to the call value (thus batched at the start of the bundle).
304
- if (address === NATIVE_ADDRESS) {
305
- value += amount;
306
- break;
307
- }
294
+ // Output transfer from the bundler.
295
+ if (from === generalAdapter1) {
308
296
  actions.push({
309
- type: "erc20TransferFrom",
310
- args: [address, amount],
297
+ type: "erc20Transfer",
298
+ args: [address, to, amount],
311
299
  });
312
300
  break;
313
301
  }
314
- // Any other transfer is ignored.
302
+ actions.push({
303
+ type: "erc20TransferFrom",
304
+ args: [address, amount, to],
305
+ });
315
306
  break;
316
307
  }
317
308
  case "Erc20_Transfer2": {
318
309
  const { amount, from, to } = operation.args;
319
- // Output transfer2 from the bundler is treated like a standard output transfer.
320
- if (from === bundler) {
321
- if (address === NATIVE_ADDRESS) {
322
- actions.push({
323
- type: "nativeTransfer",
324
- args: [to, amount],
325
- });
326
- break;
327
- }
328
- actions.push({
329
- type: "erc20Transfer",
330
- args: [address, to, amount],
331
- });
332
- break;
333
- }
334
- // Input transfer2 to the bundler.
335
- if (to === bundler) {
336
- // Native token transfer is added to the call value (thus batched at the start of the bundle).
337
- if (address === NATIVE_ADDRESS) {
338
- value += amount;
339
- break;
340
- }
341
- if (supportsSignature) {
342
- actions.push({
343
- type: "transferFrom2",
344
- args: [address, amount],
345
- });
346
- break;
347
- }
348
- // Signatures are not supported, fallback to standard transfer.
310
+ if (supportsSignature) {
349
311
  actions.push({
350
- type: "erc20TransferFrom",
351
- args: [address, amount],
312
+ type: "transferFrom2",
313
+ args: [address, from, amount, to],
352
314
  });
353
315
  break;
354
316
  }
355
- // Any other transfer is ignored.
317
+ // Signatures are not supported, fallback to standard transfer.
318
+ actions.push({
319
+ type: "erc20TransferFrom",
320
+ args: [address, amount, to],
321
+ });
356
322
  break;
357
323
  }
358
324
  case "Erc20_Wrap": {
@@ -375,15 +341,18 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
375
341
  case stEth: {
376
342
  actions.push({
377
343
  type: "stakeEth",
378
- args: [amount, 0n, zeroAddress],
344
+ args: [amount, MathLib.MAX_UINT_256, zeroAddress],
379
345
  });
380
346
  break;
381
347
  }
382
348
  default: {
383
349
  if (erc20WrapperTokens[chainId].has(address)) {
350
+ const underlying = getUnwrappedToken(address, chainId);
351
+ if (underlying == null)
352
+ throw Error(`unknown wrapped token: ${address}`);
384
353
  actions.push({
385
354
  type: "erc20WrapperDepositFor",
386
- args: [address, amount],
355
+ args: [address, underlying, amount],
387
356
  });
388
357
  break;
389
358
  }
@@ -423,21 +392,17 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
423
392
  break;
424
393
  }
425
394
  case "Blue_Supply": {
426
- const { id, assets = 0n, shares = 0n, onBehalf } = operation.args;
427
- const { params } = dataBefore.getMarket(id);
428
- // Already takes slippage into account.
429
- const slippageAmount = shares === 0n
430
- ? dataAfter.getPosition(onBehalf, id).supplyShares -
431
- dataBefore.getPosition(onBehalf, id).supplyShares
432
- : dataAfter.getHolding(sender, params.loanToken).balance -
433
- dataBefore.getHolding(sender, params.loanToken).balance;
395
+ const { id, assets = 0n, shares = 0n, onBehalf, slippage = 0n, } = operation.args;
396
+ const { params, totalSupplyAssets, totalSupplyShares } = dataBefore.getMarket(id);
397
+ const maxSharePrice = (totalSupplyAssets * MathLib.wToRay(MathLib.WAD + slippage)) /
398
+ totalSupplyShares;
434
399
  actions.push({
435
400
  type: "morphoSupply",
436
401
  args: [
437
402
  params,
438
403
  assets,
439
404
  shares,
440
- slippageAmount,
405
+ maxSharePrice,
441
406
  onBehalf,
442
407
  callbackBundle?.actions ?? [],
443
408
  ],
@@ -445,51 +410,39 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
445
410
  break;
446
411
  }
447
412
  case "Blue_Withdraw": {
448
- const { id, assets = 0n, shares = 0n, onBehalf, receiver, } = operation.args;
449
- const { params } = dataBefore.getMarket(id);
450
- // Already takes slippage into account.
451
- const slippageAmount = shares === 0n
452
- ? dataBefore.getPosition(onBehalf, id).supplyShares -
453
- dataAfter.getPosition(onBehalf, id).supplyShares
454
- : dataBefore.getHolding(sender, params.loanToken).balance -
455
- dataAfter.getHolding(sender, params.loanToken).balance;
413
+ const { id, assets = 0n, shares = 0n, receiver, slippage = 0n, } = operation.args;
414
+ const { params, totalSupplyAssets, totalSupplyShares } = dataBefore.getMarket(id);
415
+ const minSharePrice = (totalSupplyAssets * MathLib.wToRay(MathLib.WAD - slippage)) /
416
+ totalSupplyShares;
456
417
  actions.push({
457
418
  type: "morphoWithdraw",
458
- args: [params, assets, shares, slippageAmount, receiver],
419
+ args: [params, assets, shares, minSharePrice, receiver],
459
420
  });
460
421
  break;
461
422
  }
462
423
  case "Blue_Borrow": {
463
- const { id, assets = 0n, shares = 0n, onBehalf, receiver, } = operation.args;
464
- const { params } = dataBefore.getMarket(id);
465
- // Already takes slippage into account.
466
- const slippageAmount = shares === 0n
467
- ? dataAfter.getPosition(onBehalf, id).borrowShares -
468
- dataBefore.getPosition(onBehalf, id).borrowShares
469
- : dataAfter.getHolding(sender, params.loanToken).balance -
470
- dataBefore.getHolding(sender, params.loanToken).balance;
424
+ const { id, assets = 0n, shares = 0n, receiver, slippage = 0n, } = operation.args;
425
+ const { params, totalBorrowAssets, totalBorrowShares } = dataBefore.getMarket(id);
426
+ const minSharePrice = (totalBorrowAssets * MathLib.wToRay(MathLib.WAD - slippage)) /
427
+ totalBorrowShares;
471
428
  actions.push({
472
429
  type: "morphoBorrow",
473
- args: [params, assets, shares, slippageAmount, receiver],
430
+ args: [params, assets, shares, minSharePrice, receiver],
474
431
  });
475
432
  break;
476
433
  }
477
434
  case "Blue_Repay": {
478
- const { id, assets = 0n, shares = 0n, onBehalf } = operation.args;
479
- const { params } = dataBefore.getMarket(id);
480
- // Already takes slippage into account.
481
- const slippageAmount = shares === 0n
482
- ? dataBefore.getPosition(onBehalf, id).borrowShares -
483
- dataAfter.getPosition(onBehalf, id).borrowShares
484
- : dataBefore.getHolding(sender, params.loanToken).balance -
485
- dataAfter.getHolding(sender, params.loanToken).balance;
435
+ const { id, assets = 0n, shares = 0n, onBehalf, slippage = 0n, } = operation.args;
436
+ const { params, totalBorrowAssets, totalBorrowShares } = dataBefore.getMarket(id);
437
+ const maxSharePrice = (totalBorrowAssets * MathLib.wToRay(MathLib.WAD + slippage)) /
438
+ totalBorrowShares;
486
439
  actions.push({
487
440
  type: "morphoRepay",
488
441
  args: [
489
442
  params,
490
443
  assets,
491
444
  shares,
492
- slippageAmount,
445
+ maxSharePrice,
493
446
  onBehalf,
494
447
  callbackBundle?.actions ?? [],
495
448
  ],
@@ -500,9 +453,12 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
500
453
  const { id, assets, onBehalf } = operation.args;
501
454
  const { params } = dataBefore.getMarket(id);
502
455
  if (convexWrapperTokens[chainId].has(params.collateralToken)) {
456
+ const underlying = getUnwrappedToken(address, chainId);
457
+ if (underlying == null)
458
+ throw Error(`unknown wrapped token: ${address}`);
503
459
  actions.push({
504
460
  type: "erc20WrapperDepositFor",
505
- args: [params.collateralToken, assets],
461
+ args: [params.collateralToken, underlying, assets],
506
462
  });
507
463
  break;
508
464
  }
@@ -522,61 +478,46 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
522
478
  break;
523
479
  }
524
480
  case "MetaMorpho_Deposit": {
525
- const { assets = 0n, shares = 0n, owner } = operation.args;
526
- if (shares === 0n) {
527
- // Already takes slippage into account.
528
- const expectedShares = dataAfter.getHolding(owner, address).balance -
529
- dataBefore.getHolding(owner, address).balance;
481
+ const { assets = 0n, shares = 0n, owner, slippage = 0n } = operation.args;
482
+ const vault = dataBefore.getVault(address);
483
+ const maxSharePrice = (vault.totalAssets * MathLib.wToRay(MathLib.WAD + slippage)) /
484
+ vault.totalSupply;
485
+ if (shares === 0n)
530
486
  actions.push({
531
487
  type: "erc4626Deposit",
532
- args: [address, assets, expectedShares, owner],
488
+ args: [address, assets, maxSharePrice, owner],
533
489
  });
534
- }
535
- else {
536
- const vaultConfig = dataBefore.getVault(address);
537
- // Already takes slippage into account.
538
- const expectedAssets = dataBefore.getHolding(sender, vaultConfig.asset).balance -
539
- dataAfter.getHolding(sender, vaultConfig.asset).balance;
490
+ else
540
491
  actions.push({
541
492
  type: "erc4626Mint",
542
- args: [address, shares, expectedAssets, owner],
493
+ args: [address, shares, maxSharePrice, owner],
543
494
  });
544
- }
545
495
  break;
546
496
  }
547
497
  case "MetaMorpho_Withdraw": {
548
- const { assets = 0n, shares = 0n, owner, receiver } = operation.args;
549
- if (assets > 0n) {
550
- // Already takes slippage into account.
551
- const expectedShares = dataBefore.getHolding(owner, address).balance -
552
- dataAfter.getHolding(owner, address).balance;
498
+ const { assets = 0n, shares = 0n, owner, receiver, slippage = 0n, } = operation.args;
499
+ const vault = dataBefore.getVault(address);
500
+ const minSharePrice = (vault.totalAssets * MathLib.wToRay(MathLib.WAD - slippage)) /
501
+ vault.totalSupply;
502
+ if (assets > 0n)
553
503
  actions.push({
554
504
  type: "erc4626Withdraw",
555
- args: [address, assets, expectedShares, receiver, owner],
505
+ args: [address, assets, minSharePrice, receiver, owner],
556
506
  });
557
- }
558
- else {
559
- const vaultConfig = dataBefore.getVault(address);
560
- // Already takes slippage into account.
561
- const expectedAssets = dataAfter.getHolding(receiver, vaultConfig.asset).balance -
562
- dataBefore.getHolding(receiver, vaultConfig.asset).balance;
507
+ else
563
508
  actions.push({
564
509
  type: "erc4626Redeem",
565
- args: [address, shares, expectedAssets, receiver, owner],
510
+ args: [address, shares, minSharePrice, receiver, owner],
566
511
  });
567
- }
568
512
  break;
569
513
  }
570
514
  case "MetaMorpho_PublicReallocate": {
571
515
  const { withdrawals, supplyMarketId } = operation.args;
572
- if (publicAllocator == null)
573
- throw Error(`unknown public allocator on chain ${chainId}`);
574
516
  const { fee } = dataBefore.getVault(address).publicAllocatorConfig;
575
517
  // Value is already accrued via another native input transfer.
576
518
  actions.push({
577
519
  type: "reallocateTo",
578
520
  args: [
579
- publicAllocator,
580
521
  address,
581
522
  fee,
582
523
  withdrawals.map(({ id, assets }) => ({
@@ -591,15 +532,12 @@ export const encodeOperation = (operation, dataBefore, supportsSignature = true,
591
532
  }
592
533
  return {
593
534
  dataAfter,
594
- value,
595
535
  actions,
596
536
  requirements,
597
537
  };
598
538
  };
599
539
  export function encodeBundle(operations, startData, supportsSignature = true) {
600
540
  const { chainId } = startData;
601
- const { bundler } = getChainAddresses(chainId);
602
- let value = 0n;
603
541
  const actions = [];
604
542
  const requirements = {
605
543
  signatures: [],
@@ -609,7 +547,6 @@ export function encodeBundle(operations, startData, supportsSignature = true) {
609
547
  for (let index = 0; index < operations.length; ++index) {
610
548
  const bundle = encodeOperation(operations[index], steps[index], supportsSignature, index);
611
549
  steps.push(bundle.dataAfter);
612
- value += bundle.value;
613
550
  actions.push(...bundle.actions);
614
551
  requirements.signatures.push(...bundle.requirements.signatures);
615
552
  requirements.txs.push(...bundle.requirements.txs);
@@ -618,14 +555,6 @@ export function encodeBundle(operations, startData, supportsSignature = true) {
618
555
  steps,
619
556
  actions,
620
557
  requirements,
621
- tx: () => ({
622
- to: bundler,
623
- value,
624
- data: encodeFunctionData({
625
- abi: baseBundlerAbi,
626
- functionName: "multicall",
627
- args: [actions.map(BundlerAction.encode)],
628
- }),
629
- }),
558
+ tx: () => BundlerAction.encodeBundle(chainId, actions),
630
559
  };
631
560
  }
package/lib/errors.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { SimulationResult } from "@morpho-org/simulation-sdk";
2
- import type { InputBundlerOperation } from "./types/index.js";
2
+ import type { ActionType, InputBundlerOperation } from "./types/index.js";
3
3
  export declare namespace BundlerErrors {
4
4
  class Bundle extends Error {
5
5
  readonly error: Error;
@@ -11,4 +11,7 @@ export declare namespace BundlerErrors {
11
11
  class MissingSignature extends Error {
12
12
  constructor();
13
13
  }
14
+ class UnexpectedAction extends Error {
15
+ constructor(type: ActionType, chainId: number);
16
+ }
14
17
  }
package/lib/errors.js CHANGED
@@ -21,4 +21,10 @@ export var BundlerErrors;
21
21
  }
22
22
  }
23
23
  BundlerErrors.MissingSignature = MissingSignature;
24
+ class UnexpectedAction extends Error {
25
+ constructor(type, chainId) {
26
+ super(`unexpected action "${type}" on chain "${chainId}"`);
27
+ }
28
+ }
29
+ BundlerErrors.UnexpectedAction = UnexpectedAction;
24
30
  })(BundlerErrors || (BundlerErrors = {}));