@matterlabs/zksync-js 0.0.13 → 0.0.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.
Files changed (66) hide show
  1. package/dist/adapters/ethers/client.cjs +13 -4
  2. package/dist/adapters/ethers/client.cjs.map +1 -1
  3. package/dist/adapters/ethers/client.js +7 -6
  4. package/dist/adapters/ethers/index.cjs +501 -242
  5. package/dist/adapters/ethers/index.cjs.map +1 -1
  6. package/dist/adapters/ethers/index.js +10 -9
  7. package/dist/adapters/ethers/resources/deposits/routes/priority.d.ts +12 -0
  8. package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +4 -0
  9. package/dist/adapters/ethers/resources/interop/index.d.ts +14 -14
  10. package/dist/adapters/ethers/resources/interop/resolvers.d.ts +3 -8
  11. package/dist/adapters/ethers/resources/interop/routes/types.d.ts +2 -1
  12. package/dist/adapters/ethers/resources/interop/services/erc20.d.ts +10 -0
  13. package/dist/adapters/ethers/resources/interop/services/fee.d.ts +12 -0
  14. package/dist/adapters/ethers/resources/interop/services/finalization/index.d.ts +1 -1
  15. package/dist/adapters/ethers/resources/interop/services/finalization/polling.d.ts +1 -1
  16. package/dist/adapters/ethers/resources/interop/types.d.ts +6 -14
  17. package/dist/adapters/ethers/sdk.cjs +912 -252
  18. package/dist/adapters/ethers/sdk.cjs.map +1 -1
  19. package/dist/adapters/ethers/sdk.d.ts +6 -1
  20. package/dist/adapters/ethers/sdk.js +8 -7
  21. package/dist/adapters/viem/client.cjs +8 -4
  22. package/dist/adapters/viem/client.cjs.map +1 -1
  23. package/dist/adapters/viem/client.js +7 -6
  24. package/dist/adapters/viem/index.cjs +315 -73
  25. package/dist/adapters/viem/index.cjs.map +1 -1
  26. package/dist/adapters/viem/index.js +10 -9
  27. package/dist/adapters/viem/resources/deposits/routes/priority.d.ts +13 -0
  28. package/dist/adapters/viem/resources/deposits/services/gas.d.ts +4 -0
  29. package/dist/adapters/viem/sdk.cjs +307 -69
  30. package/dist/adapters/viem/sdk.cjs.map +1 -1
  31. package/dist/adapters/viem/sdk.js +7 -7
  32. package/dist/{chunk-E3KP7XCG.js → chunk-3HHUZXSV.js} +1 -1
  33. package/dist/{chunk-UDBRUBEK.js → chunk-5RRJDPAJ.js} +2 -2
  34. package/dist/{chunk-EDWBCPO3.js → chunk-75IOOODG.js} +253 -53
  35. package/dist/{chunk-R5WRFPK2.js → chunk-7CAVFIMW.js} +5 -4
  36. package/dist/chunk-BWKWWLY4.js +9 -0
  37. package/dist/{chunk-4S4XDA4N.js → chunk-DYJKK5FW.js} +17 -15
  38. package/dist/{chunk-5L6EYUJB.js → chunk-EOBXYHTZ.js} +35 -7
  39. package/dist/{chunk-53MC5BR2.js → chunk-HP3EWKJL.js} +1 -1
  40. package/dist/{chunk-HI64OOAR.js → chunk-J47RI3G7.js} +1 -1
  41. package/dist/{chunk-RI73VJSH.js → chunk-JY62QO3W.js} +44 -21
  42. package/dist/{chunk-QQ2OR434.js → chunk-MT4X5FEO.js} +18 -2
  43. package/dist/{chunk-2RIARDXZ.js → chunk-OTXPSNNC.js} +5 -4
  44. package/dist/{chunk-5R7L5NM5.js → chunk-XDRCN4FC.js} +2 -2
  45. package/dist/{chunk-JHO2UQ5F.js → chunk-XKRNLFET.js} +394 -200
  46. package/dist/core/constants.cjs +17 -1
  47. package/dist/core/constants.cjs.map +1 -1
  48. package/dist/core/constants.d.ts +9 -1
  49. package/dist/core/constants.js +1 -1
  50. package/dist/core/index.cjs +52 -24
  51. package/dist/core/index.cjs.map +1 -1
  52. package/dist/core/index.js +6 -5
  53. package/dist/core/internal/abis/IERC7786Attributes.d.ts +21 -11
  54. package/dist/core/internal/abis/IInteropCenter.d.ts +4 -0
  55. package/dist/core/resources/deposits/priority.d.ts +37 -0
  56. package/dist/core/resources/interop/attributes/bundle.d.ts +1 -0
  57. package/dist/core/resources/interop/attributes/resource.d.ts +1 -0
  58. package/dist/core/resources/interop/plan.d.ts +11 -3
  59. package/dist/core/rpc/types.d.ts +1 -0
  60. package/dist/core/rpc/zks.d.ts +5 -1
  61. package/dist/core/types/errors.d.ts +5 -0
  62. package/dist/core/types/flows/interop.d.ts +11 -18
  63. package/dist/index.cjs +69 -25
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.js +6 -5
  66. package/package.json +1 -1
@@ -48,7 +48,15 @@ var TX_OVERHEAD_GAS = 10000n;
48
48
  var TX_MEMORY_OVERHEAD_GAS = 10n;
49
49
  var DEFAULT_PUBDATA_BYTES = 155n;
50
50
  var DEFAULT_ABI_BYTES = 400n;
51
- var SAFE_L1_BRIDGE_GAS = 800000n;
51
+ var SAFE_L1_BRIDGE_GAS = 3000000n;
52
+ var L1_TX_INTRINSIC_L2_GAS = 167157n;
53
+ var L1_TX_INTRINSIC_PUBDATA = 88n;
54
+ var L1_TX_MIN_L2_GAS_BASE = 173484n;
55
+ var L1_TX_DELTA_544_ENCODING_BYTES = 1656n;
56
+ var L1_TX_DELTA_FACTORY_DEPS_L2_GAS = 2473n;
57
+ var L1_TX_DELTA_FACTORY_DEPS_PUBDATA = 64n;
58
+ var TX_SLOT_OVERHEAD_L2_GAS = 10000n;
59
+ var PRIORITY_TX_MAX_GAS_LIMIT = 72000000n;
52
60
 
53
61
  // src/core/utils/addr.ts
54
62
  function isAddress(x) {
@@ -413,6 +421,11 @@ var OP_INTEROP = {
413
421
  wait: {
414
422
  poll: "interop.svc.wait:poll",
415
423
  timeout: "interop.svc.wait:timeout"
424
+ },
425
+ fees: {
426
+ zkInteropFee: "interop.svc.fees:zkInteropFee",
427
+ zkToken: "interop.svc.fees:zkToken",
428
+ protocolFee: "interop.svc.fees:protocolFee"
416
429
  }
417
430
  }
418
431
  };
@@ -481,6 +494,7 @@ function normalizeProof(p) {
481
494
  const raw = p ?? {};
482
495
  const idRaw = raw?.id ?? raw?.index;
483
496
  const bnRaw = raw?.batch_number ?? raw?.batchNumber;
497
+ const gwBlockNumberRaw = raw?.gatewayBlockNumber;
484
498
  if (idRaw == null || bnRaw == null) {
485
499
  throw createError("RPC", {
486
500
  resource: "zksrpc",
@@ -501,7 +515,8 @@ function normalizeProof(p) {
501
515
  id: toBig(idRaw),
502
516
  batchNumber: toBig(bnRaw),
503
517
  proof: toHexArray(raw?.proof),
504
- root: raw.root
518
+ root: raw.root,
519
+ gatewayBlockNumber: gwBlockNumberRaw != null ? toBig(gwBlockNumberRaw) : void 0
505
520
  };
506
521
  } catch (e) {
507
522
  if (isZKsyncError(e)) throw e;
@@ -778,13 +793,15 @@ function createZksRpc(transport) {
778
793
  );
779
794
  },
780
795
  // Fetches a proof for an L2→L1 log emitted in the given transaction.
781
- async getL2ToL1LogProof(txHash, index) {
796
+ async getL2ToL1LogProof(txHash, index, proofTarget) {
782
797
  return withRpcOp(
783
798
  "zksrpc.getL2ToL1LogProof",
784
799
  "Failed to fetch L2\u2192L1 log proof.",
785
- { txHash, index },
800
+ { txHash, index, proofTarget },
786
801
  async () => {
787
- const proof = await transport(METHODS.getL2ToL1LogProof, [txHash, index]);
802
+ const params = [txHash, index];
803
+ if (proofTarget != void 0) params.push(proofTarget);
804
+ const proof = await transport(METHODS.getL2ToL1LogProof, params);
788
805
  if (!proof) {
789
806
  throw createError("STATE", {
790
807
  resource: "zksrpc",
@@ -4967,56 +4984,69 @@ var IERC20_default = IERC20ABI;
4967
4984
  // src/core/internal/abis/IERC7786Attributes.ts
4968
4985
  var IERC7786AttributesABI = [
4969
4986
  {
4987
+ type: "function",
4988
+ name: "executionAddress",
4970
4989
  inputs: [
4971
4990
  {
4972
- internalType: "bytes",
4973
4991
  name: "_executionAddress",
4974
- type: "bytes"
4992
+ type: "bytes",
4993
+ internalType: "bytes"
4975
4994
  }
4976
4995
  ],
4977
- name: "executionAddress",
4978
4996
  outputs: [],
4979
- stateMutability: "pure",
4980
- type: "function"
4997
+ stateMutability: "pure"
4981
4998
  },
4982
4999
  {
5000
+ type: "function",
5001
+ name: "indirectCall",
4983
5002
  inputs: [
4984
5003
  {
4985
- internalType: "uint256",
4986
5004
  name: "_indirectCallMessageValue",
4987
- type: "uint256"
5005
+ type: "uint256",
5006
+ internalType: "uint256"
4988
5007
  }
4989
5008
  ],
4990
- name: "indirectCall",
4991
5009
  outputs: [],
4992
- stateMutability: "pure",
4993
- type: "function"
5010
+ stateMutability: "pure"
4994
5011
  },
4995
5012
  {
5013
+ type: "function",
5014
+ name: "interopCallValue",
4996
5015
  inputs: [
4997
5016
  {
4998
- internalType: "uint256",
4999
5017
  name: "_interopCallValue",
5000
- type: "uint256"
5018
+ type: "uint256",
5019
+ internalType: "uint256"
5001
5020
  }
5002
5021
  ],
5003
- name: "interopCallValue",
5004
5022
  outputs: [],
5005
- stateMutability: "pure",
5006
- type: "function"
5023
+ stateMutability: "pure"
5007
5024
  },
5008
5025
  {
5026
+ type: "function",
5027
+ name: "unbundlerAddress",
5009
5028
  inputs: [
5010
5029
  {
5011
- internalType: "bytes",
5012
5030
  name: "_unbundlerAddress",
5013
- type: "bytes"
5031
+ type: "bytes",
5032
+ internalType: "bytes"
5014
5033
  }
5015
5034
  ],
5016
- name: "unbundlerAddress",
5017
5035
  outputs: [],
5018
- stateMutability: "pure",
5019
- type: "function"
5036
+ stateMutability: "pure"
5037
+ },
5038
+ {
5039
+ type: "function",
5040
+ name: "useFixedFee",
5041
+ inputs: [
5042
+ {
5043
+ name: "_useFixed",
5044
+ type: "bool",
5045
+ internalType: "bool"
5046
+ }
5047
+ ],
5048
+ outputs: [],
5049
+ stateMutability: "pure"
5020
5050
  }
5021
5051
  ];
5022
5052
  var IERC7786Attributes_default = IERC7786AttributesABI;
@@ -5864,6 +5894,11 @@ var IInteropCenterABI = [
5864
5894
  type: "uint256",
5865
5895
  internalType: "uint256"
5866
5896
  },
5897
+ {
5898
+ name: "destinationBaseTokenAssetId",
5899
+ type: "bytes32",
5900
+ internalType: "bytes32"
5901
+ },
5867
5902
  {
5868
5903
  name: "interopBundleSalt",
5869
5904
  type: "bytes32",
@@ -7498,7 +7533,7 @@ function createErrorOps(decodeRevert2) {
7498
7533
  throw toZKsyncError2(kind, { resource, operation, context: opts?.ctx ?? {}, message }, e);
7499
7534
  }
7500
7535
  }
7501
- function wrap7(operation, fn, opts) {
7536
+ function wrap8(operation, fn, opts) {
7502
7537
  return run("INTERNAL", operation, fn, opts);
7503
7538
  }
7504
7539
  function wrapAs10(kind, operation, fn, opts) {
@@ -7506,7 +7541,7 @@ function createErrorOps(decodeRevert2) {
7506
7541
  }
7507
7542
  async function toResult3(operation, fn, opts) {
7508
7543
  try {
7509
- const value = await wrap7(operation, fn, opts);
7544
+ const value = await wrap8(operation, fn, opts);
7510
7545
  return { ok: true, value };
7511
7546
  } catch (e) {
7512
7547
  const shaped = isZKsyncError(e) ? e : toZKsyncError2(
@@ -7522,7 +7557,7 @@ function createErrorOps(decodeRevert2) {
7522
7557
  return { ok: false, error: shaped };
7523
7558
  }
7524
7559
  }
7525
- return { wrap: wrap7, wrapAs: wrapAs10, toResult: toResult3 };
7560
+ return { wrap: wrap8, wrapAs: wrapAs10, toResult: toResult3 };
7526
7561
  }
7527
7562
  return { toZKsyncError: toZKsyncError2, createErrorHandlers: createErrorHandlers2 };
7528
7563
  }
@@ -8054,11 +8089,10 @@ async function quoteL1Gas(input) {
8054
8089
  const est = await estimator.estimateGas(tx);
8055
8090
  const buffered = BigInt(est) * (100n + BUFFER) / 100n;
8056
8091
  return makeGasQuote({ gasLimit: buffered, maxFeePerGas, maxPriorityFeePerGas });
8057
- } catch (err) {
8092
+ } catch {
8058
8093
  if (fallbackGasLimit != null) {
8059
8094
  return makeGasQuote({ gasLimit: fallbackGasLimit, maxFeePerGas, maxPriorityFeePerGas });
8060
8095
  }
8061
- console.warn("L1 gas estimation failed", err);
8062
8096
  return void 0;
8063
8097
  }
8064
8098
  }
@@ -8096,8 +8130,7 @@ async function quoteL2Gas(input) {
8096
8130
  maxFeePerGas,
8097
8131
  gasPerPubdata: pp
8098
8132
  });
8099
- } catch (err) {
8100
- console.warn("L2 gas estimation failed", err);
8133
+ } catch {
8101
8134
  return makeGasQuote({
8102
8135
  gasLimit: l2GasLimit ?? 0n,
8103
8136
  maxFeePerGas,
@@ -8260,8 +8293,22 @@ async function determineNonBaseL2Gas(input) {
8260
8293
  try {
8261
8294
  const l2TokenAddress = input.knownL2Token ?? (ctx.tokens ? await ctx.tokens.toL2Address(l1Token) : await (await ctx.contracts.l2NativeTokenVault()).l2TokenAddress(l1Token));
8262
8295
  if (l2TokenAddress === ZERO_L2_TOKEN_ADDRESS) {
8296
+ if (input.undeployedGasLimit != null) {
8297
+ return quoteL2Gas2({
8298
+ ctx,
8299
+ route,
8300
+ overrideGasLimit: input.undeployedGasLimit
8301
+ });
8302
+ }
8263
8303
  return fallbackQuote();
8264
8304
  }
8305
+ if (input.priorityFloorGasLimit != null) {
8306
+ return quoteL2Gas2({
8307
+ ctx,
8308
+ route,
8309
+ overrideGasLimit: input.priorityFloorGasLimit
8310
+ });
8311
+ }
8265
8312
  const modelTx = {
8266
8313
  to: input.modelTx?.to ?? ctx.sender,
8267
8314
  from: input.modelTx?.from ?? ctx.sender,
@@ -8277,8 +8324,7 @@ async function determineNonBaseL2Gas(input) {
8277
8324
  return fallbackQuote();
8278
8325
  }
8279
8326
  return gas;
8280
- } catch (err) {
8281
- console.warn("Failed to determine non-base deposit L2 gas; defaulting to safe gas limit.", err);
8327
+ } catch {
8282
8328
  return fallbackQuote();
8283
8329
  }
8284
8330
  }
@@ -8295,7 +8341,9 @@ async function determineEthNonBaseL2Gas(input) {
8295
8341
  route: "eth-nonbase",
8296
8342
  l1Token: input.ctx.resolvedToken?.l1 ?? FORMAL_ETH_ADDRESS,
8297
8343
  knownL2Token: input.ctx.resolvedToken?.l2,
8298
- modelTx: input.modelTx
8344
+ modelTx: input.modelTx,
8345
+ priorityFloorGasLimit: input.priorityFloorGasLimit,
8346
+ undeployedGasLimit: input.undeployedGasLimit
8299
8347
  });
8300
8348
  }
8301
8349
 
@@ -8327,41 +8375,112 @@ function buildFeeBreakdown(p) {
8327
8375
  };
8328
8376
  }
8329
8377
 
8378
+ // src/core/resources/deposits/priority.ts
8379
+ var PRIORITY_TX_ENCODING_STEP_BYTES = 544n;
8380
+ var DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER = 6n;
8381
+ var maxBigInt = (a, b) => a > b ? a : b;
8382
+ var ceilDiv = (a, b) => (a + b - 1n) / b;
8383
+ function derivePriorityTxGasBreakdown(input) {
8384
+ const factoryDepsCount = input.factoryDepsCount ?? 0n;
8385
+ const minBodyGas = maxBigInt(
8386
+ L1_TX_INTRINSIC_L2_GAS + ceilDiv(
8387
+ input.encodedLength * L1_TX_DELTA_544_ENCODING_BYTES,
8388
+ PRIORITY_TX_ENCODING_STEP_BYTES
8389
+ ) + factoryDepsCount * L1_TX_DELTA_FACTORY_DEPS_L2_GAS,
8390
+ L1_TX_MIN_L2_GAS_BASE
8391
+ ) + L1_TX_INTRINSIC_PUBDATA * input.gasPerPubdata + factoryDepsCount * L1_TX_DELTA_FACTORY_DEPS_PUBDATA * input.gasPerPubdata;
8392
+ const overhead = maxBigInt(TX_SLOT_OVERHEAD_L2_GAS, TX_MEMORY_OVERHEAD_GAS * input.encodedLength);
8393
+ const derivedBodyGas = minBodyGas;
8394
+ return {
8395
+ encodedLength: input.encodedLength,
8396
+ minBodyGas,
8397
+ overhead,
8398
+ derivedBodyGas,
8399
+ derivedL2GasLimit: derivedBodyGas + overhead,
8400
+ priorityTxMaxGasLimit: PRIORITY_TX_MAX_GAS_LIMIT,
8401
+ priorityTxMaxGasLimitExceeded: derivedBodyGas > PRIORITY_TX_MAX_GAS_LIMIT
8402
+ };
8403
+ }
8404
+ function derivePriorityBodyGasEstimateCap(input) {
8405
+ return input.minBodyGas * (input.multiplier ?? DEFAULT_PRIORITY_BODY_GAS_ESTIMATE_MULTIPLIER);
8406
+ }
8407
+
8408
+ // src/adapters/ethers/resources/deposits/routes/priority.ts
8409
+ var EMPTY_BYTES = "0x";
8410
+ var ZERO_RESERVED_WORDS = [0n, 0n, 0n, 0n];
8411
+ var L2_CANONICAL_TRANSACTION_TUPLE = "tuple(uint256 txType,uint256 from,uint256 to,uint256 gasLimit,uint256 gasPerPubdataByteLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,uint256 paymaster,uint256 nonce,uint256 value,uint256[4] reserved,bytes data,bytes signature,uint256[] factoryDeps,bytes paymasterInput,bytes reservedDynamic)";
8412
+ function hexByteLength(hex) {
8413
+ return BigInt(Math.max(hex.length - 2, 0) / 2);
8414
+ }
8415
+ function getPriorityTxEncodedLength(input) {
8416
+ const encoded = ethers.AbiCoder.defaultAbiCoder().encode(
8417
+ [L2_CANONICAL_TRANSACTION_TUPLE],
8418
+ [
8419
+ [
8420
+ 0n,
8421
+ BigInt(input.sender),
8422
+ BigInt(input.l2Contract),
8423
+ 0n,
8424
+ input.gasPerPubdata,
8425
+ 0n,
8426
+ 0n,
8427
+ 0n,
8428
+ 0n,
8429
+ input.l2Value,
8430
+ ZERO_RESERVED_WORDS,
8431
+ input.l2Calldata,
8432
+ EMPTY_BYTES,
8433
+ input.factoryDepsHashes ?? [],
8434
+ EMPTY_BYTES,
8435
+ EMPTY_BYTES
8436
+ ]
8437
+ ]
8438
+ );
8439
+ return hexByteLength(encoded);
8440
+ }
8441
+ function getPriorityTxGasBreakdown(input) {
8442
+ return derivePriorityTxGasBreakdown({
8443
+ encodedLength: getPriorityTxEncodedLength(input),
8444
+ gasPerPubdata: input.gasPerPubdata,
8445
+ factoryDepsCount: BigInt(input.factoryDepsHashes?.length ?? 0)
8446
+ });
8447
+ }
8448
+
8330
8449
  // src/adapters/ethers/resources/deposits/routes/eth.ts
8450
+ var EMPTY_BYTES2 = "0x";
8331
8451
  function routeEthDirect() {
8332
8452
  return {
8333
8453
  async build(p, ctx) {
8334
8454
  const bh = await ctx.contracts.bridgehub();
8335
- const l2TxModel = {
8336
- to: p.to ?? ctx.sender,
8337
- from: ctx.sender,
8338
- data: "0x",
8339
- value: 0n
8340
- };
8455
+ const l2Contract = p.to ?? ctx.sender;
8456
+ const l2Value = p.amount;
8457
+ const l2Calldata = EMPTY_BYTES2;
8458
+ const priorityFloorBreakdown = getPriorityTxGasBreakdown({
8459
+ sender: ctx.sender,
8460
+ l2Contract,
8461
+ l2Value,
8462
+ l2Calldata,
8463
+ gasPerPubdata: ctx.gasPerPubdata
8464
+ });
8465
+ const quotedL2GasLimit = ctx.l2GasLimit ?? priorityFloorBreakdown.derivedL2GasLimit;
8341
8466
  const l2GasParams = await quoteL2Gas2({
8342
8467
  ctx,
8343
8468
  route: "eth-base",
8344
- l2TxForModeling: l2TxModel,
8345
- overrideGasLimit: ctx.l2GasLimit,
8346
- stateOverrides: {
8347
- [ctx.sender]: {
8348
- balance: "0xffffffffffffffffffff"
8349
- }
8350
- }
8469
+ overrideGasLimit: quotedL2GasLimit
8351
8470
  });
8352
8471
  if (!l2GasParams) {
8353
8472
  throw new Error("Failed to estimate L2 gas for deposit.");
8354
8473
  }
8355
8474
  const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
8356
- const mintValue = baseCost + ctx.operatorTip + p.amount;
8475
+ const mintValue = baseCost + ctx.operatorTip + l2Value;
8357
8476
  const req = buildDirectRequestStruct({
8358
8477
  chainId: ctx.chainIdL2,
8359
8478
  mintValue,
8360
8479
  l2GasLimit: l2GasParams.gasLimit,
8361
8480
  gasPerPubdata: ctx.gasPerPubdata,
8362
8481
  refundRecipient: ctx.refundRecipient,
8363
- l2Contract: p.to ?? ctx.sender,
8364
- l2Value: p.amount
8482
+ l2Contract,
8483
+ l2Value
8365
8484
  });
8366
8485
  const data = bh.interface.encodeFunctionData("requestL2TransactionDirect", [req]);
8367
8486
  const l1TxCandidate = {
@@ -8406,6 +8525,53 @@ function routeEthDirect() {
8406
8525
  };
8407
8526
  }
8408
8527
  var { wrapAs: wrapAs3 } = createErrorHandlers("deposits");
8528
+ var ZERO_L2_TOKEN_ADDRESS2 = "0x0000000000000000000000000000000000000000";
8529
+ var ZERO_ASSET_ID = "0x0000000000000000000000000000000000000000000000000000000000000000";
8530
+ async function getPriorityGasModel(input) {
8531
+ try {
8532
+ const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
8533
+ const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
8534
+ const { chainId: l1ChainId } = await input.ctx.client.l1.getNetwork();
8535
+ const isFirstBridge = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID || input.ctx.resolvedToken.originChainId === 0n;
8536
+ const erc20MetadataOriginChainId = isFirstBridge ? BigInt(l1ChainId) : input.ctx.resolvedToken.originChainId;
8537
+ const erc20Metadata = await l1NativeTokenVault.getERC20Getters(
8538
+ input.token,
8539
+ erc20MetadataOriginChainId
8540
+ );
8541
+ const bridgeMintCalldata = ethers.AbiCoder.defaultAbiCoder().encode(
8542
+ ["address", "address", "address", "uint256", "bytes"],
8543
+ [input.ctx.sender, input.receiver, input.token, input.amount, erc20Metadata]
8544
+ );
8545
+ const l2Calldata = isFirstBridge ? new ethers.Interface(IL2AssetRouter_default).encodeFunctionData(
8546
+ "finalizeDeposit(address,address,address,uint256,bytes)",
8547
+ [input.ctx.sender, input.receiver, input.token, input.amount, erc20Metadata]
8548
+ ) : await (() => {
8549
+ return l1AssetRouter.getDepositCalldata(
8550
+ input.ctx.sender,
8551
+ input.ctx.resolvedToken.assetId,
8552
+ bridgeMintCalldata
8553
+ );
8554
+ })();
8555
+ const priorityFloorBreakdown = getPriorityTxGasBreakdown({
8556
+ sender: input.ctx.l1AssetRouter,
8557
+ l2Contract: L2_ASSET_ROUTER_ADDRESS,
8558
+ l2Value: 0n,
8559
+ l2Calldata,
8560
+ gasPerPubdata: input.ctx.gasPerPubdata
8561
+ });
8562
+ const model = {
8563
+ priorityFloorGasLimit: priorityFloorBreakdown.derivedL2GasLimit
8564
+ };
8565
+ if (isFirstBridge || input.ctx.resolvedToken.l2.toLowerCase() === ZERO_L2_TOKEN_ADDRESS2) {
8566
+ model.undeployedGasLimit = derivePriorityBodyGasEstimateCap({
8567
+ minBodyGas: priorityFloorBreakdown.minBodyGas
8568
+ }) + priorityFloorBreakdown.overhead;
8569
+ }
8570
+ return model;
8571
+ } catch {
8572
+ return {};
8573
+ }
8574
+ }
8409
8575
  function routeErc20NonBase() {
8410
8576
  return {
8411
8577
  async preflight(p, ctx) {
@@ -8426,11 +8592,29 @@ function routeErc20NonBase() {
8426
8592
  const l1Signer = ctx.client.getL1Signer();
8427
8593
  const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
8428
8594
  const baseIsEth = ctx.baseIsEth ?? isETH(baseToken);
8595
+ const receiver = p.to ?? ctx.sender;
8596
+ const secondBridgeCalldata = await wrapAs3(
8597
+ "INTERNAL",
8598
+ OP_DEPOSITS.nonbase.encodeCalldata,
8599
+ () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, receiver)),
8600
+ {
8601
+ ctx: { where: "encodeSecondBridgeErc20Args" },
8602
+ message: "Failed to encode bridging calldata."
8603
+ }
8604
+ );
8605
+ const priorityGasModel = await getPriorityGasModel({
8606
+ ctx,
8607
+ token: p.token,
8608
+ amount: p.amount,
8609
+ receiver
8610
+ });
8429
8611
  const l2GasParams = await determineErc20L2Gas({
8430
8612
  ctx,
8431
8613
  l1Token: p.token,
8614
+ priorityFloorGasLimit: priorityGasModel.priorityFloorGasLimit,
8615
+ undeployedGasLimit: priorityGasModel.undeployedGasLimit,
8432
8616
  modelTx: {
8433
- to: p.to ?? ctx.sender,
8617
+ to: receiver,
8434
8618
  from: ctx.sender,
8435
8619
  data: "0x",
8436
8620
  value: 0n
@@ -8492,15 +8676,6 @@ function routeErc20NonBase() {
8492
8676
  });
8493
8677
  }
8494
8678
  }
8495
- const secondBridgeCalldata = await wrapAs3(
8496
- "INTERNAL",
8497
- OP_DEPOSITS.nonbase.encodeCalldata,
8498
- () => Promise.resolve(encodeSecondBridgeErc20Args(p.token, p.amount, p.to ?? ctx.sender)),
8499
- {
8500
- ctx: { where: "encodeSecondBridgeErc20Args" },
8501
- message: "Failed to encode bridging calldata."
8502
- }
8503
- );
8504
8679
  const requestStruct = {
8505
8680
  chainId: ctx.chainIdL2,
8506
8681
  mintValue,
@@ -8557,7 +8732,68 @@ function routeErc20NonBase() {
8557
8732
  }
8558
8733
  };
8559
8734
  }
8735
+
8736
+ // src/core/codec/ntv.ts
8737
+ function createNTVCodec(deps) {
8738
+ function encodeAssetId(originChainId, ntvAddress, tokenAddress) {
8739
+ const encoded = deps.encode(
8740
+ ["uint256", "address", "address"],
8741
+ [originChainId, ntvAddress, tokenAddress]
8742
+ );
8743
+ return deps.keccak256(encoded);
8744
+ }
8745
+ return {
8746
+ encodeAssetId
8747
+ };
8748
+ }
8749
+
8750
+ // src/adapters/ethers/resources/deposits/routes/eth-nonbase.ts
8560
8751
  var { wrapAs: wrapAs4 } = createErrorHandlers("deposits");
8752
+ var ZERO_L2_TOKEN_ADDRESS3 = "0x0000000000000000000000000000000000000000";
8753
+ var ZERO_ASSET_ID2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
8754
+ var ntvCodec = createNTVCodec({
8755
+ encode: (types, values) => ethers.AbiCoder.defaultAbiCoder().encode(types, values),
8756
+ keccak256: (data) => ethers.keccak256(data)
8757
+ });
8758
+ async function getPriorityGasModel2(input) {
8759
+ try {
8760
+ const l1AssetRouter = await input.ctx.contracts.l1AssetRouter();
8761
+ const l1NativeTokenVault = await input.ctx.contracts.l1NativeTokenVault();
8762
+ const originChainId = input.ctx.resolvedToken.originChainId !== 0n ? input.ctx.resolvedToken.originChainId : BigInt((await input.ctx.client.l1.getNetwork()).chainId);
8763
+ const resolvedAssetId = input.ctx.resolvedToken.assetId.toLowerCase() === ZERO_ASSET_ID2 ? ntvCodec.encodeAssetId(originChainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, ETH_ADDRESS) : input.ctx.resolvedToken.assetId;
8764
+ const erc20Metadata = await l1NativeTokenVault.getERC20Getters(
8765
+ ETH_ADDRESS,
8766
+ originChainId
8767
+ );
8768
+ const bridgeMintCalldata = ethers.AbiCoder.defaultAbiCoder().encode(
8769
+ ["address", "address", "address", "uint256", "bytes"],
8770
+ [input.ctx.sender, input.receiver, ETH_ADDRESS, input.amount, erc20Metadata]
8771
+ );
8772
+ const l2Calldata = await l1AssetRouter.getDepositCalldata(
8773
+ input.ctx.sender,
8774
+ resolvedAssetId,
8775
+ bridgeMintCalldata
8776
+ );
8777
+ const priorityFloorBreakdown = getPriorityTxGasBreakdown({
8778
+ sender: input.ctx.l1AssetRouter,
8779
+ l2Contract: L2_ASSET_ROUTER_ADDRESS,
8780
+ l2Value: 0n,
8781
+ l2Calldata,
8782
+ gasPerPubdata: input.ctx.gasPerPubdata
8783
+ });
8784
+ const model = {
8785
+ priorityFloorGasLimit: priorityFloorBreakdown.derivedL2GasLimit
8786
+ };
8787
+ if (input.ctx.resolvedToken.l2.toLowerCase() === ZERO_L2_TOKEN_ADDRESS3) {
8788
+ model.undeployedGasLimit = derivePriorityBodyGasEstimateCap({
8789
+ minBodyGas: priorityFloorBreakdown.minBodyGas
8790
+ }) + priorityFloorBreakdown.overhead;
8791
+ }
8792
+ return model;
8793
+ } catch {
8794
+ return {};
8795
+ }
8796
+ }
8561
8797
  function routeEthNonBase() {
8562
8798
  return {
8563
8799
  async preflight(p, ctx) {
@@ -8606,15 +8842,23 @@ function routeEthNonBase() {
8606
8842
  async build(p, ctx) {
8607
8843
  const l1Signer = ctx.client.getL1Signer();
8608
8844
  const baseToken = ctx.baseTokenL1;
8845
+ const receiver = p.to ?? ctx.sender;
8846
+ const priorityGasModel = await getPriorityGasModel2({
8847
+ ctx,
8848
+ amount: p.amount,
8849
+ receiver
8850
+ });
8609
8851
  const l2TxModel = {
8610
- to: p.to ?? ctx.sender,
8852
+ to: receiver,
8611
8853
  from: ctx.sender,
8612
8854
  data: "0x",
8613
8855
  value: 0n
8614
8856
  };
8615
8857
  const l2GasParams = await determineEthNonBaseL2Gas({
8616
8858
  ctx,
8617
- modelTx: l2TxModel
8859
+ modelTx: l2TxModel,
8860
+ priorityFloorGasLimit: priorityGasModel.priorityFloorGasLimit,
8861
+ undeployedGasLimit: priorityGasModel.undeployedGasLimit
8618
8862
  });
8619
8863
  if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
8620
8864
  const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
@@ -8648,12 +8892,12 @@ function routeEthNonBase() {
8648
8892
  const secondBridgeCalldata = await wrapAs4(
8649
8893
  "INTERNAL",
8650
8894
  OP_DEPOSITS.ethNonBase.encodeCalldata,
8651
- () => Promise.resolve(encodeSecondBridgeEthArgs(p.amount, p.to ?? ctx.sender)),
8895
+ () => Promise.resolve(encodeSecondBridgeEthArgs(p.amount, receiver)),
8652
8896
  {
8653
8897
  ctx: {
8654
8898
  where: "encodeSecondBridgeEthArgs",
8655
8899
  amount: p.amount.toString(),
8656
- to: p.to ?? ctx.sender
8900
+ to: receiver
8657
8901
  }
8658
8902
  }
8659
8903
  );
@@ -8714,6 +8958,7 @@ function routeEthNonBase() {
8714
8958
  };
8715
8959
  }
8716
8960
  var { wrapAs: wrapAs5 } = createErrorHandlers("deposits");
8961
+ var EMPTY_BYTES3 = "0x";
8717
8962
  function routeErc20Base() {
8718
8963
  return {
8719
8964
  async preflight(p, ctx) {
@@ -8744,17 +8989,21 @@ function routeErc20Base() {
8744
8989
  async build(p, ctx) {
8745
8990
  const l1Signer = ctx.client.getL1Signer();
8746
8991
  const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
8747
- const l2TxModel = {
8748
- to: p.to ?? ctx.sender,
8749
- from: ctx.sender,
8750
- data: "0x",
8751
- value: 0n
8752
- };
8992
+ const l2Contract = p.to ?? ctx.sender;
8993
+ const l2Value = p.amount;
8994
+ const l2Calldata = EMPTY_BYTES3;
8995
+ const priorityFloorBreakdown = getPriorityTxGasBreakdown({
8996
+ sender: ctx.sender,
8997
+ l2Contract,
8998
+ l2Value,
8999
+ l2Calldata,
9000
+ gasPerPubdata: ctx.gasPerPubdata
9001
+ });
9002
+ const quotedL2GasLimit = ctx.l2GasLimit ?? priorityFloorBreakdown.derivedL2GasLimit;
8753
9003
  const l2GasParams = await quoteL2Gas2({
8754
9004
  ctx,
8755
9005
  route: "erc20-base",
8756
- l2TxForModeling: l2TxModel,
8757
- overrideGasLimit: ctx.l2GasLimit
9006
+ overrideGasLimit: quotedL2GasLimit
8758
9007
  });
8759
9008
  if (!l2GasParams) throw new Error("Failed to estimate L2 gas parameters.");
8760
9009
  const baseCost = await quoteL2BaseCost2({ ctx, l2GasLimit: l2GasParams.gasLimit });
@@ -8793,8 +9042,8 @@ function routeErc20Base() {
8793
9042
  l2GasLimit: l2GasParams.gasLimit,
8794
9043
  gasPerPubdata: ctx.gasPerPubdata,
8795
9044
  refundRecipient: ctx.refundRecipient,
8796
- l2Contract: p.to ?? ctx.sender,
8797
- l2Value: p.amount
9045
+ l2Contract,
9046
+ l2Value
8798
9047
  });
8799
9048
  const bridgehub = await ctx.contracts.bridgehub();
8800
9049
  const data = bridgehub.interface.encodeFunctionData("requestL2TransactionDirect", [
@@ -8841,25 +9090,9 @@ function routeErc20Base() {
8841
9090
  }
8842
9091
  };
8843
9092
  }
8844
-
8845
- // src/core/codec/ntv.ts
8846
- function createNTVCodec(deps) {
8847
- function encodeAssetId(originChainId, ntvAddress, tokenAddress) {
8848
- const encoded = deps.encode(
8849
- ["uint256", "address", "address"],
8850
- [originChainId, ntvAddress, tokenAddress]
8851
- );
8852
- return deps.keccak256(encoded);
8853
- }
8854
- return {
8855
- encodeAssetId
8856
- };
8857
- }
8858
-
8859
- // src/adapters/ethers/resources/tokens/tokens.ts
8860
9093
  var { wrapAs: wrapAs6 } = createErrorHandlers("tokens");
8861
9094
  var abi = ethers.AbiCoder.defaultAbiCoder();
8862
- var ntvCodec = createNTVCodec({
9095
+ var ntvCodec2 = createNTVCodec({
8863
9096
  encode: (types, values) => abi.encode(types, values),
8864
9097
  keccak256: (data) => ethers.ethers.keccak256(data)
8865
9098
  });
@@ -8978,7 +9211,7 @@ function createTokensResource(client) {
8978
9211
  return wrapAs6("CONTRACT", "tokens.isChainEthBased", async () => {
8979
9212
  const baseAssetId = await getBaseTokenAssetId();
8980
9213
  const l1ChainId = await getL1ChainId();
8981
- const ethAssetId = ntvCodec.encodeAssetId(
9214
+ const ethAssetId = ntvCodec2.encodeAssetId(
8982
9215
  l1ChainId,
8983
9216
  L2_NATIVE_TOKEN_VAULT_ADDRESS,
8984
9217
  ETH_ADDRESS
@@ -9989,7 +10222,7 @@ var ROUTES2 = {
9989
10222
  };
9990
10223
  function createWithdrawalsResource(client, tokens, contracts) {
9991
10224
  const svc = createFinalizationServices(client);
9992
- const { wrap: wrap7, toResult: toResult3 } = createErrorHandlers("withdrawals");
10225
+ const { wrap: wrap8, toResult: toResult3 } = createErrorHandlers("withdrawals");
9993
10226
  const tokensResource = tokens ?? createTokensResource(client);
9994
10227
  const contractsResource = contracts ?? createContractsResource(client);
9995
10228
  async function buildPlan(p) {
@@ -10010,7 +10243,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
10010
10243
  };
10011
10244
  }
10012
10245
  const finalizeCache = /* @__PURE__ */ new Map();
10013
- const quote = (p) => wrap7(
10246
+ const quote = (p) => wrap8(
10014
10247
  OP_WITHDRAWALS.quote,
10015
10248
  async () => {
10016
10249
  const plan = await buildPlan(p);
@@ -10032,7 +10265,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
10032
10265
  ctx: { token: p.token, where: "withdrawals.tryQuote" }
10033
10266
  }
10034
10267
  );
10035
- const prepare = (p) => wrap7(OP_WITHDRAWALS.prepare, () => buildPlan(p), {
10268
+ const prepare = (p) => wrap8(OP_WITHDRAWALS.prepare, () => buildPlan(p), {
10036
10269
  message: "Internal error while preparing a withdrawal plan.",
10037
10270
  ctx: { token: p.token, where: "withdrawals.prepare" }
10038
10271
  });
@@ -10040,7 +10273,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
10040
10273
  message: "Internal error while preparing a withdrawal plan.",
10041
10274
  ctx: { token: p.token, where: "withdrawals.tryPrepare" }
10042
10275
  });
10043
- const create = (p) => wrap7(
10276
+ const create = (p) => wrap8(
10044
10277
  OP_WITHDRAWALS.create,
10045
10278
  async () => {
10046
10279
  const plan = await prepare(p);
@@ -10111,7 +10344,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
10111
10344
  message: "Internal error while creating withdrawal transactions.",
10112
10345
  ctx: { token: p.token, amount: p.amount, to: p.to, where: "withdrawals.tryCreate" }
10113
10346
  });
10114
- const status = (h) => wrap7(
10347
+ const status = (h) => wrap8(
10115
10348
  OP_WITHDRAWALS.status,
10116
10349
  async () => {
10117
10350
  const l2TxHash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
@@ -10166,7 +10399,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
10166
10399
  const wait = (h, opts = {
10167
10400
  for: "l2",
10168
10401
  pollMs: 5500
10169
- }) => wrap7(
10402
+ }) => wrap8(
10170
10403
  OP_WITHDRAWALS.wait,
10171
10404
  async () => {
10172
10405
  const l2Hash = typeof h === "string" ? h : "l2TxHash" in h && h.l2TxHash ? h.l2TxHash : "0x";
@@ -10231,7 +10464,7 @@ function createWithdrawalsResource(client, tokens, contracts) {
10231
10464
  }
10232
10465
  }
10233
10466
  );
10234
- const finalize = (l2TxHash) => wrap7(
10467
+ const finalize = (l2TxHash) => wrap8(
10235
10468
  OP_WITHDRAWALS.finalize.send,
10236
10469
  async () => {
10237
10470
  const pack = await (async () => {
@@ -10357,9 +10590,11 @@ function createCallAttributes(codec) {
10357
10590
  function createBundleAttributes(codec) {
10358
10591
  const executionAddress = (executor) => codec.encode("executionAddress", [executor]);
10359
10592
  const unbundlerAddress = (addr) => codec.encode("unbundlerAddress", [addr]);
10593
+ const useFixedFee = (enabled) => codec.encode("useFixedFee", [enabled]);
10360
10594
  return {
10361
10595
  executionAddress,
10362
- unbundlerAddress
10596
+ unbundlerAddress,
10597
+ useFixedFee
10363
10598
  };
10364
10599
  }
10365
10600
 
@@ -10380,6 +10615,7 @@ function getInteropAttributes(params, ctx) {
10380
10615
  if (params.unbundling?.by) {
10381
10616
  bundleAttributes.push(ctx.attributes.bundle.unbundlerAddress(params.unbundling.by));
10382
10617
  }
10618
+ bundleAttributes.push(ctx.attributes.bundle.useFixedFee(params.fee?.useFixed ?? false));
10383
10619
  const callAttributes = params.actions.map((action) => {
10384
10620
  switch (action.type) {
10385
10621
  case "sendNative": {
@@ -10409,11 +10645,6 @@ function createEthersAttributesResource(opts = {}) {
10409
10645
  }
10410
10646
 
10411
10647
  // src/core/types/flows/interop.ts
10412
- function isInteropExpectedRoot(obj) {
10413
- if (typeof obj !== "object" || obj === null) return false;
10414
- const root = obj;
10415
- return isBigint(root.rootChainId) && isBigint(root.batchNumber) && isHash(root.expectedRoot);
10416
- }
10417
10648
  function isInteropMessageProof(obj) {
10418
10649
  if (typeof obj !== "object" || obj === null) return false;
10419
10650
  const proof = obj;
@@ -10422,7 +10653,7 @@ function isInteropMessageProof(obj) {
10422
10653
  function isInteropFinalizationInfo(obj) {
10423
10654
  if (typeof obj !== "object" || obj === null) return false;
10424
10655
  const info = obj;
10425
- return isHash66(info.l2SrcTxHash) && isHash66(info.bundleHash) && isBigint(info.dstChainId) && isHash(info.encodedData) && isInteropExpectedRoot(info.expectedRoot) && isInteropMessageProof(info.proof);
10656
+ return isHash66(info.l2SrcTxHash) && isHash66(info.bundleHash) && isBigint(info.dstChainId) && isHash(info.encodedData) && isInteropMessageProof(info.proof);
10426
10657
  }
10427
10658
 
10428
10659
  // src/core/resources/interop/route.ts
@@ -10475,7 +10706,7 @@ function preflightDirect(params, ctx) {
10475
10706
  }
10476
10707
  }
10477
10708
  }
10478
- function buildDirectBundle(params, ctx, attrs) {
10709
+ function buildDirectBundle(params, ctx, attrs, interopFeeInfo) {
10479
10710
  const totalActionValue = sumActionMsgValue(params.actions);
10480
10711
  const starters = params.actions.map((action, index) => {
10481
10712
  const to = ctx.codec.formatAddress(action.to);
@@ -10493,7 +10724,8 @@ function buildDirectBundle(params, ctx, attrs) {
10493
10724
  dstChain: ctx.codec.formatChain(ctx.dstChainId),
10494
10725
  starters,
10495
10726
  bundleAttributes: attrs.bundleAttributes,
10496
- approvals: [],
10727
+ approvals: interopFeeInfo.approval ? [interopFeeInfo.approval] : [],
10728
+ interopFee: interopFeeInfo.fee,
10497
10729
  quoteExtras: {
10498
10730
  totalActionValue,
10499
10731
  bridgedTokenTotal: 0n
@@ -10538,7 +10770,7 @@ function preflightIndirect(params, ctx) {
10538
10770
  }
10539
10771
  }
10540
10772
  }
10541
- function buildIndirectBundle(params, ctx, attrs, starterData) {
10773
+ function buildIndirectBundle(params, ctx, attrs, starterData, interopFeeInfo) {
10542
10774
  const totalActionValue = sumActionMsgValue(params.actions);
10543
10775
  const bridgedTokenTotal = sumErc20Amounts(params.actions);
10544
10776
  const approvalMap = /* @__PURE__ */ new Map();
@@ -10557,6 +10789,7 @@ function buildIndirectBundle(params, ctx, attrs, starterData) {
10557
10789
  }
10558
10790
  }
10559
10791
  const approvals = Array.from(approvalMap.values());
10792
+ if (interopFeeInfo.approval) approvals.push(interopFeeInfo.approval);
10560
10793
  const starters = params.actions.map((action, index) => {
10561
10794
  const callAttributes = attrs.callAttributes[index] ?? [];
10562
10795
  if (starterData[index]?.assetRouterPayload) {
@@ -10580,6 +10813,7 @@ function buildIndirectBundle(params, ctx, attrs, starterData) {
10580
10813
  starters,
10581
10814
  bundleAttributes: attrs.bundleAttributes,
10582
10815
  approvals,
10816
+ interopFee: interopFeeInfo.fee,
10583
10817
  quoteExtras: {
10584
10818
  totalActionValue,
10585
10819
  bridgedTokenTotal
@@ -10626,6 +10860,29 @@ function buildEnsureTokenSteps(erc20Tokens, ctx) {
10626
10860
  }
10627
10861
  }));
10628
10862
  }
10863
+ async function buildApproveSteps(approvals, ctx) {
10864
+ const steps = [];
10865
+ for (const approval of approvals) {
10866
+ const erc20 = new ethers.Contract(approval.token, IERC20_default, ctx.client.l2);
10867
+ const currentAllowance = await erc20.allowance(ctx.sender, approval.spender);
10868
+ if (currentAllowance < approval.amount) {
10869
+ steps.push({
10870
+ key: `approve:${approval.token}:${approval.spender}`,
10871
+ kind: "approve",
10872
+ description: `Approve ${approval.spender} to spend ${approval.amount} of ${approval.token}`,
10873
+ tx: {
10874
+ to: approval.token,
10875
+ data: erc20.interface.encodeFunctionData("approve", [
10876
+ approval.spender,
10877
+ approval.amount
10878
+ ]),
10879
+ ...ctx.gasOverrides
10880
+ }
10881
+ });
10882
+ }
10883
+ }
10884
+ return steps;
10885
+ }
10629
10886
  async function resolveErc20AssetIds(erc20Tokens, ctx) {
10630
10887
  const assetIds = /* @__PURE__ */ new Map();
10631
10888
  if (erc20Tokens.length === 0) return assetIds;
@@ -10679,6 +10936,44 @@ async function getStarterData(params, ctx, erc20AssetIds) {
10679
10936
  }
10680
10937
  return starterData;
10681
10938
  }
10939
+ var { wrap: wrap3 } = createErrorHandlers("interop");
10940
+ async function buildFeeInfo(params, ctx, numStarters) {
10941
+ const useFixed = params.fee?.useFixed ?? false;
10942
+ const interopCenter = new ethers.Contract(ctx.interopCenter, IInteropCenter_default, ctx.client.l2);
10943
+ if (useFixed) {
10944
+ const zkFeePerCall = await wrap3(
10945
+ OP_INTEROP.svc.fees.zkInteropFee,
10946
+ () => interopCenter.ZK_INTEROP_FEE(),
10947
+ { message: "Failed to fetch ZK interop fee from InteropCenter." }
10948
+ );
10949
+ const zkFeeTotal = zkFeePerCall * BigInt(numStarters);
10950
+ const zkTokenAddress = await wrap3(
10951
+ OP_INTEROP.svc.fees.zkToken,
10952
+ () => interopCenter.zkToken(),
10953
+ { message: "Failed to fetch ZK token address from InteropCenter." }
10954
+ );
10955
+ const approval = {
10956
+ token: zkTokenAddress,
10957
+ spender: ctx.interopCenter,
10958
+ amount: zkFeeTotal
10959
+ };
10960
+ return {
10961
+ approval,
10962
+ fee: { token: zkTokenAddress, amount: zkFeeTotal }
10963
+ };
10964
+ } else {
10965
+ const protocolFeePerCall = await wrap3(
10966
+ OP_INTEROP.svc.fees.protocolFee,
10967
+ () => interopCenter.interopProtocolFee(),
10968
+ { message: "Failed to fetch interop protocol fee from InteropCenter." }
10969
+ );
10970
+ const totalFee = protocolFeePerCall * BigInt(numStarters);
10971
+ return {
10972
+ approval: null,
10973
+ fee: { token: ctx.baseTokens.src, amount: totalFee }
10974
+ };
10975
+ }
10976
+ }
10682
10977
 
10683
10978
  // src/adapters/ethers/resources/interop/routes/indirect.ts
10684
10979
  function routeIndirect() {
@@ -10694,7 +10989,10 @@ function routeIndirect() {
10694
10989
  async build(params, ctx) {
10695
10990
  const steps = [];
10696
10991
  const erc20Tokens = getErc20Tokens(params);
10697
- const erc20AssetIds = await resolveErc20AssetIds(erc20Tokens, ctx);
10992
+ const [erc20AssetIds, feeInfo] = await Promise.all([
10993
+ resolveErc20AssetIds(erc20Tokens, ctx),
10994
+ buildFeeInfo(params, ctx, params.actions.length)
10995
+ ]);
10698
10996
  const attributes = getInteropAttributes(params, ctx);
10699
10997
  const starterData = await getStarterData(params, ctx, erc20AssetIds);
10700
10998
  const bundle = buildIndirectBundle(
@@ -10707,32 +11005,11 @@ function routeIndirect() {
10707
11005
  codec: interopCodec
10708
11006
  },
10709
11007
  attributes,
10710
- starterData
11008
+ starterData,
11009
+ feeInfo
10711
11010
  );
10712
11011
  steps.push(...buildEnsureTokenSteps(erc20Tokens, ctx));
10713
- for (const approval of bundle.approvals) {
10714
- const erc20 = new ethers.Contract(approval.token, IERC20_default, ctx.client.l2);
10715
- const currentAllowance = await erc20.allowance(
10716
- ctx.sender,
10717
- ctx.l2NativeTokenVault
10718
- );
10719
- if (currentAllowance < approval.amount) {
10720
- const approveData = erc20.interface.encodeFunctionData("approve", [
10721
- ctx.l2NativeTokenVault,
10722
- approval.amount
10723
- ]);
10724
- steps.push({
10725
- key: `approve:${approval.token}:${ctx.l2NativeTokenVault}`,
10726
- kind: "approve",
10727
- description: `Approve ${ctx.l2NativeTokenVault} to spend ${approval.amount} of ${approval.token}`,
10728
- tx: {
10729
- to: approval.token,
10730
- data: approveData,
10731
- ...ctx.gasOverrides
10732
- }
10733
- });
10734
- }
10735
- }
11012
+ steps.push(...await buildApproveSteps(bundle.approvals, ctx));
10736
11013
  const data = ctx.ifaces.interopCenter.encodeFunctionData("sendBundle", [
10737
11014
  bundle.dstChain,
10738
11015
  bundle.starters,
@@ -10745,14 +11022,15 @@ function routeIndirect() {
10745
11022
  tx: {
10746
11023
  to: ctx.interopCenter,
10747
11024
  data,
10748
- value: bundle.quoteExtras.totalActionValue,
11025
+ value: bundle.quoteExtras.totalActionValue + feeInfo.fee.amount,
10749
11026
  ...ctx.gasOverrides
10750
11027
  }
10751
11028
  });
10752
11029
  return {
10753
11030
  steps,
10754
11031
  approvals: bundle.approvals,
10755
- quoteExtras: bundle.quoteExtras
11032
+ quoteExtras: bundle.quoteExtras,
11033
+ interopFee: feeInfo.fee
10756
11034
  };
10757
11035
  }
10758
11036
  };
@@ -10769,10 +11047,10 @@ function routeDirect() {
10769
11047
  l2AssetRouter: ctx.l2AssetRouter,
10770
11048
  l2NativeTokenVault: ctx.l2NativeTokenVault});
10771
11049
  },
10772
- // eslint-disable-next-line @typescript-eslint/require-await
10773
11050
  async build(params, ctx) {
10774
11051
  const steps = [];
10775
11052
  const attrs = getInteropAttributes(params, ctx);
11053
+ const feeInfo = await buildFeeInfo(params, ctx, params.actions.length);
10776
11054
  const built = buildDirectBundle(
10777
11055
  params,
10778
11056
  {
@@ -10782,8 +11060,10 @@ function routeDirect() {
10782
11060
  l2NativeTokenVault: ctx.l2NativeTokenVault,
10783
11061
  codec: interopCodec
10784
11062
  },
10785
- attrs
11063
+ attrs,
11064
+ feeInfo
10786
11065
  );
11066
+ steps.push(...await buildApproveSteps(built.approvals, ctx));
10787
11067
  const data = ctx.ifaces.interopCenter.encodeFunctionData("sendBundle", [
10788
11068
  built.dstChain,
10789
11069
  built.starters,
@@ -10793,19 +11073,19 @@ function routeDirect() {
10793
11073
  key: "sendBundle",
10794
11074
  kind: "interop.center",
10795
11075
  description: `Send interop bundle (direct route; ${params.actions.length} actions)`,
10796
- // In direct route, msg.value equals the total forwarded value across
10797
- // all calls (sendNative.amount + call.value).
11076
+ // msg.value = forwarded action value + protocol fee.
10798
11077
  tx: {
10799
11078
  to: ctx.interopCenter,
10800
11079
  data,
10801
- value: built.quoteExtras.totalActionValue,
11080
+ value: built.quoteExtras.totalActionValue + feeInfo.fee.amount,
10802
11081
  ...ctx.gasOverrides
10803
11082
  }
10804
11083
  });
10805
11084
  return {
10806
11085
  steps,
10807
11086
  approvals: built.approvals,
10808
- quoteExtras: built.quoteExtras
11087
+ quoteExtras: built.quoteExtras,
11088
+ interopFee: feeInfo.fee
10809
11089
  };
10810
11090
  }
10811
11091
  };
@@ -10885,7 +11165,7 @@ function getTopics() {
10885
11165
  };
10886
11166
  return { topics, centerIface };
10887
11167
  }
10888
- var { wrap: wrap3 } = createErrorHandlers("interop");
11168
+ var { wrap: wrap4 } = createErrorHandlers("interop");
10889
11169
  var DEFAULT_BLOCKS_RANGE_SIZE = 1e4;
10890
11170
  var DEFAULT_MAX_BLOCKS_BACK = 2e4;
10891
11171
  var SAFE_BLOCKS_RANGE_SIZE = 1e3;
@@ -10898,7 +11178,7 @@ function parseMaxBlockRangeLimit(error) {
10898
11178
  return Number.isInteger(limit) && limit > 0 ? limit : null;
10899
11179
  }
10900
11180
  async function getTxReceipt(provider, txHash) {
10901
- const receipt = await wrap3(
11181
+ const receipt = await wrap4(
10902
11182
  OP_INTEROP.svc.status.sourceReceipt,
10903
11183
  () => provider.getTransactionReceipt(txHash),
10904
11184
  {
@@ -10919,7 +11199,7 @@ async function getTxReceipt(provider, txHash) {
10919
11199
  async function getLogs(provider, address, topics, opts) {
10920
11200
  const maxBlocksBack = opts?.maxBlocksBack ?? DEFAULT_MAX_BLOCKS_BACK;
10921
11201
  const initialChunkSize = opts?.logChunkSize ?? DEFAULT_BLOCKS_RANGE_SIZE;
10922
- return await wrap3(
11202
+ return await wrap4(
10923
11203
  OP_INTEROP.svc.status.dstLogs,
10924
11204
  async () => {
10925
11205
  const currentBlock = await provider.getBlockNumber();
@@ -10966,7 +11246,7 @@ async function getLogs(provider, address, topics, opts) {
10966
11246
  );
10967
11247
  }
10968
11248
  async function getInteropRoot(provider, rootChainId, batchNumber) {
10969
- return await wrap3(
11249
+ return await wrap4(
10970
11250
  OP_INTEROP.svc.status.getRoot,
10971
11251
  async () => {
10972
11252
  const rootStorage = new ethers.Contract(
@@ -10984,7 +11264,7 @@ async function getInteropRoot(provider, rootChainId, batchNumber) {
10984
11264
  }
10985
11265
 
10986
11266
  // src/adapters/ethers/resources/interop/services/finalization/bundle.ts
10987
- var { wrap: wrap4 } = createErrorHandlers("interop");
11267
+ var { wrap: wrap5 } = createErrorHandlers("interop");
10988
11268
  async function getBundleStatus(client, dstProvider, topics, bundleHash, opts) {
10989
11269
  const { interopHandler } = await client.ensureAddresses();
10990
11270
  const bundleLogs = await getLogs(dstProvider, interopHandler, [null, bundleHash], opts);
@@ -11016,7 +11296,7 @@ async function executeBundle(client, dstProvider, info, opts) {
11016
11296
  context: { bundleHash }
11017
11297
  });
11018
11298
  }
11019
- const signer = await wrap4(OP_INTEROP.exec.sendStep, () => client.signerFor(dstProvider), {
11299
+ const signer = await wrap5(OP_INTEROP.exec.sendStep, () => client.signerFor(dstProvider), {
11020
11300
  message: "Failed to resolve destination signer."
11021
11301
  });
11022
11302
  const { interopHandler } = await client.ensureAddresses();
@@ -11178,11 +11458,6 @@ function getBundleEncodedData(messageData) {
11178
11458
  return `0x${messageData.slice(4)}`;
11179
11459
  }
11180
11460
  function buildFinalizationInfo(ids, bundleInfo, proof, messageData) {
11181
- const expectedRoot = {
11182
- rootChainId: bundleInfo.sourceChainId,
11183
- batchNumber: proof.batchNumber,
11184
- expectedRoot: proof.root
11185
- };
11186
11461
  const messageProof = {
11187
11462
  chainId: bundleInfo.sourceChainId,
11188
11463
  l1BatchNumber: proof.batchNumber,
@@ -11198,7 +11473,6 @@ function buildFinalizationInfo(ids, bundleInfo, proof, messageData) {
11198
11473
  l2SrcTxHash: ids.l2SrcTxHash,
11199
11474
  bundleHash: bundleInfo.bundleHash,
11200
11475
  dstChainId: bundleInfo.dstChainId,
11201
- expectedRoot,
11202
11476
  proof: messageProof,
11203
11477
  encodedData: getBundleEncodedData(messageData)
11204
11478
  };
@@ -11221,7 +11495,7 @@ function decodeL1MessageData(log) {
11221
11495
  }
11222
11496
 
11223
11497
  // src/adapters/ethers/resources/interop/services/finalization/polling.ts
11224
- var { wrap: wrap5 } = createErrorHandlers("interop");
11498
+ var { wrap: wrap6 } = createErrorHandlers("interop");
11225
11499
  function isProofNotReadyError(error) {
11226
11500
  return isZKsyncError(error, {
11227
11501
  operation: "zksrpc.getL2ToL1LogProof",
@@ -11258,30 +11532,26 @@ async function waitForProof(client, l2SrcTxHash, logIndex, blockNumber, pollMs,
11258
11532
  });
11259
11533
  }
11260
11534
  try {
11261
- return await client.zks.getL2ToL1LogProof(l2SrcTxHash, logIndex);
11535
+ return await client.zks.getL2ToL1LogProof(l2SrcTxHash, logIndex, "messageRoot" /* MessageRoot */);
11262
11536
  } catch (error) {
11263
11537
  if (!isProofNotReadyError(error)) throw error;
11264
11538
  }
11265
11539
  await sleep(pollMs);
11266
11540
  }
11267
11541
  }
11268
- async function waitForRoot(provider, expectedRoot, pollMs, deadline) {
11542
+ async function waitForRoot(provider, chainId, batchNumber, pollMs, deadline) {
11269
11543
  while (true) {
11270
11544
  if (Date.now() > deadline) {
11271
11545
  throw createError("TIMEOUT", {
11272
11546
  resource: "interop",
11273
11547
  operation: OP_INTEROP.svc.wait.timeout,
11274
11548
  message: "Timed out waiting for interop root to become available.",
11275
- context: { expectedRoot }
11549
+ context: { chainId, batchNumber }
11276
11550
  });
11277
11551
  }
11278
11552
  let interopRoot = null;
11279
11553
  try {
11280
- const root = await getInteropRoot(
11281
- provider,
11282
- expectedRoot.rootChainId,
11283
- expectedRoot.batchNumber
11284
- );
11554
+ const root = await getInteropRoot(provider, chainId, batchNumber);
11285
11555
  if (root !== ZERO_HASH) {
11286
11556
  interopRoot = root;
11287
11557
  }
@@ -11290,18 +11560,7 @@ async function waitForRoot(provider, expectedRoot, pollMs, deadline) {
11290
11560
  interopRoot = null;
11291
11561
  }
11292
11562
  if (interopRoot) {
11293
- if (interopRoot.toLowerCase() === expectedRoot.expectedRoot.toLowerCase()) {
11294
- return;
11295
- }
11296
- throw createError("STATE", {
11297
- resource: "interop",
11298
- operation: OP_INTEROP.wait,
11299
- message: "Interop root mismatch.",
11300
- context: {
11301
- expected: expectedRoot.expectedRoot,
11302
- got: interopRoot
11303
- }
11304
- });
11563
+ return interopRoot;
11305
11564
  }
11306
11565
  await sleep(pollMs);
11307
11566
  }
@@ -11316,7 +11575,7 @@ async function waitForTxReceipt(client, txHash, pollMs, deadline) {
11316
11575
  context: { txHash }
11317
11576
  });
11318
11577
  }
11319
- const receipt = await wrap5(
11578
+ const receipt = await wrap6(
11320
11579
  OP_INTEROP.svc.status.sourceReceipt,
11321
11580
  () => client.zks.getReceiptWithL2ToL1(txHash),
11322
11581
  {
@@ -11330,7 +11589,7 @@ async function waitForTxReceipt(client, txHash, pollMs, deadline) {
11330
11589
  await sleep(pollMs);
11331
11590
  }
11332
11591
  }
11333
- async function waitForFinalization(client, dstProvider, input, opts) {
11592
+ async function waitForFinalization(client, dstProvider, gwProvider, input, opts) {
11334
11593
  const { topics, centerIface } = getTopics();
11335
11594
  const pollMs = opts?.pollMs ?? DEFAULT_POLL_MS;
11336
11595
  const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
@@ -11379,7 +11638,16 @@ async function waitForFinalization(client, dstProvider, input, opts) {
11379
11638
  proof,
11380
11639
  bundleInfo.l1MessageData
11381
11640
  );
11382
- await waitForRoot(dstProvider, finalizationInfo.expectedRoot, pollMs, deadline);
11641
+ if (proof.gatewayBlockNumber == null) {
11642
+ throw createError("STATE", {
11643
+ resource: "interop",
11644
+ operation: OP_INTEROP.svc.wait.timeout,
11645
+ message: "Proof missing gatewayBlockNumber required for interop finalization.",
11646
+ context: { l2SrcTxHash: ids.l2SrcTxHash }
11647
+ });
11648
+ }
11649
+ const { chainId: gwChainId } = await gwProvider.getNetwork();
11650
+ await waitForRoot(dstProvider, gwChainId, proof.gatewayBlockNumber, pollMs, deadline);
11383
11651
  return finalizationInfo;
11384
11652
  }
11385
11653
 
@@ -11425,8 +11693,8 @@ function createInteropFinalizationServices(client) {
11425
11693
  status(dstProvider, input, opts) {
11426
11694
  return getStatus(client, dstProvider, input, opts);
11427
11695
  },
11428
- wait(dstProvider, input, opts) {
11429
- return waitForFinalization(client, dstProvider, input, opts);
11696
+ wait(dstProvider, gwProvider, input, opts) {
11697
+ return waitForFinalization(client, dstProvider, gwProvider, input, opts);
11430
11698
  },
11431
11699
  async finalize(dstProvider, info, opts) {
11432
11700
  const execResult = await executeBundle(client, dstProvider, info, opts);
@@ -11438,24 +11706,31 @@ function createInteropFinalizationServices(client) {
11438
11706
  }
11439
11707
  };
11440
11708
  }
11441
- function resolveDstProvider(dstChain) {
11442
- return typeof dstChain === "string" ? new ethers.JsonRpcProvider(dstChain) : dstChain;
11443
- }
11444
- function resolveWaitableInput(waitableInput) {
11445
- const input = waitableInput;
11446
- return {
11447
- dstProvider: resolveDstProvider(waitableInput.dstChain),
11448
- waitable: input.waitable ? input.waitable : waitableInput
11449
- };
11709
+ function resolveChainRef(ref) {
11710
+ return typeof ref === "string" ? new ethers.JsonRpcProvider(ref) : ref;
11450
11711
  }
11451
11712
 
11452
11713
  // src/adapters/ethers/resources/interop/index.ts
11453
- var { wrap: wrap6, toResult: toResult2 } = createErrorHandlers("interop");
11714
+ var { wrap: wrap7, toResult: toResult2 } = createErrorHandlers("interop");
11454
11715
  var ROUTES3 = {
11455
11716
  direct: routeDirect(),
11456
11717
  indirect: routeIndirect()
11457
11718
  };
11458
- function createInteropResource(client, tokens, contracts, attributes) {
11719
+ function createInteropResource(client, config, tokens, contracts, attributes) {
11720
+ let gwProviderCache;
11721
+ function requireConfig() {
11722
+ if (!config)
11723
+ throw createError("STATE", {
11724
+ resource: "interop",
11725
+ operation: "interop.init",
11726
+ message: "Interop is not configured. Pass gwChain in createEthersSdk options."
11727
+ });
11728
+ return config;
11729
+ }
11730
+ function getGwProvider() {
11731
+ if (!gwProviderCache) gwProviderCache = resolveChainRef(requireConfig().gwChain);
11732
+ return gwProviderCache;
11733
+ }
11459
11734
  const svc = createInteropFinalizationServices(client);
11460
11735
  const tokensResource = tokens ?? createTokensResource(client);
11461
11736
  const contractsResource = contracts ?? createContractsResource(client);
@@ -11479,11 +11754,11 @@ function createInteropResource(client, tokens, contracts, attributes) {
11479
11754
  baseTokenDst: ctx.baseTokens.dst
11480
11755
  }
11481
11756
  });
11482
- await wrap6(OP_INTEROP.routes[route].preflight, () => ROUTES3[route].preflight?.(params, ctx), {
11757
+ await wrap7(OP_INTEROP.routes[route].preflight, () => ROUTES3[route].preflight?.(params, ctx), {
11483
11758
  message: "Interop preflight failed.",
11484
11759
  ctx: { where: `routes.${route}.preflight` }
11485
11760
  });
11486
- const { steps, approvals, quoteExtras } = await wrap6(
11761
+ const { steps, approvals, quoteExtras, interopFee } = await wrap7(
11487
11762
  OP_INTEROP.routes[route].build,
11488
11763
  () => ROUTES3[route].build(params, ctx),
11489
11764
  {
@@ -11495,7 +11770,8 @@ function createInteropResource(client, tokens, contracts, attributes) {
11495
11770
  route,
11496
11771
  approvalsNeeded: approvals,
11497
11772
  totalActionValue: quoteExtras.totalActionValue,
11498
- bridgedTokenTotal: quoteExtras.bridgedTokenTotal
11773
+ bridgedTokenTotal: quoteExtras.bridgedTokenTotal,
11774
+ interopFee
11499
11775
  };
11500
11776
  return { plan: { route, summary, steps }, ctx };
11501
11777
  }
@@ -11503,20 +11779,23 @@ function createInteropResource(client, tokens, contracts, attributes) {
11503
11779
  const { plan } = await buildPlanWithCtx(dstProvider, params);
11504
11780
  return plan;
11505
11781
  }
11506
- const quote = (params) => wrap6(OP_INTEROP.quote, async () => {
11507
- const plan = await buildPlan(resolveDstProvider(params.dstChain), params);
11782
+ const quote = (dstChain, params) => wrap7(OP_INTEROP.quote, async () => {
11783
+ const plan = await buildPlan(resolveChainRef(dstChain), params);
11508
11784
  return plan.summary;
11509
11785
  });
11510
- const tryQuote = (params) => toResult2(OP_INTEROP.tryQuote, () => quote(params));
11511
- const prepare = (params) => wrap6(OP_INTEROP.prepare, () => buildPlan(resolveDstProvider(params.dstChain), params), {
11786
+ const tryQuote = (dstChain, params) => toResult2(OP_INTEROP.tryQuote, () => quote(dstChain, params));
11787
+ const prepare = (dstChain, params) => wrap7(OP_INTEROP.prepare, () => buildPlan(resolveChainRef(dstChain), params), {
11512
11788
  message: "Internal error while preparing an interop plan.",
11513
11789
  ctx: { where: "interop.prepare" }
11514
11790
  });
11515
- const tryPrepare = (params) => toResult2(OP_INTEROP.tryPrepare, () => prepare(params));
11516
- const create = (params) => wrap6(
11791
+ const tryPrepare = (dstChain, params) => toResult2(
11792
+ OP_INTEROP.tryPrepare,
11793
+ () => prepare(dstChain, params)
11794
+ );
11795
+ const create = (dstChain, params) => wrap7(
11517
11796
  OP_INTEROP.create,
11518
11797
  async () => {
11519
- const { plan, ctx } = await buildPlanWithCtx(resolveDstProvider(params.dstChain), params);
11798
+ const { plan, ctx } = await buildPlanWithCtx(resolveChainRef(dstChain), params);
11520
11799
  const signer = ctx.client.signerFor(ctx.client.l2);
11521
11800
  const srcProvider = ctx.client.l2;
11522
11801
  const from = await signer.getAddress();
@@ -11578,7 +11857,6 @@ function createInteropResource(client, tokens, contracts, attributes) {
11578
11857
  const last = Object.values(stepHashes).pop();
11579
11858
  return {
11580
11859
  kind: "interop",
11581
- dstChain: params.dstChain,
11582
11860
  stepHashes,
11583
11861
  plan,
11584
11862
  l2SrcTxHash: last ?? "0x"
@@ -11589,46 +11867,27 @@ function createInteropResource(client, tokens, contracts, attributes) {
11589
11867
  ctx: { where: "interop.create" }
11590
11868
  }
11591
11869
  );
11592
- const tryCreate = (params) => toResult2(OP_INTEROP.tryCreate, () => create(params));
11593
- const status = (h, opts) => {
11594
- const { dstProvider, waitable } = resolveWaitableInput(h);
11595
- return wrap6(OP_INTEROP.status, () => svc.status(dstProvider, waitable, opts), {
11596
- message: "Internal error while checking interop status.",
11597
- ctx: { where: "interop.status" }
11598
- });
11599
- };
11600
- const wait = (h, opts) => {
11601
- const { dstProvider, waitable } = resolveWaitableInput(h);
11602
- return wrap6(
11603
- OP_INTEROP.wait,
11604
- async () => {
11605
- const info = await svc.wait(dstProvider, waitable, opts);
11606
- return { ...info, dstChain: h.dstChain };
11607
- },
11608
- {
11609
- message: "Internal error while waiting for interop finalization.",
11610
- ctx: { where: "interop.wait" }
11611
- }
11612
- );
11613
- };
11614
- const tryWait = (h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(h, opts));
11615
- const finalize = (h, opts) => wrap6(
11870
+ const tryCreate = (dstChain, params) => toResult2(
11871
+ OP_INTEROP.tryCreate,
11872
+ () => create(dstChain, params)
11873
+ );
11874
+ const status = (dstChain, h, opts) => wrap7(OP_INTEROP.status, () => svc.status(resolveChainRef(dstChain), h, opts), {
11875
+ message: "Internal error while checking interop status.",
11876
+ ctx: { where: "interop.status" }
11877
+ });
11878
+ const wait = (dstChain, h, opts) => wrap7(OP_INTEROP.wait, () => svc.wait(resolveChainRef(dstChain), getGwProvider(), h, opts), {
11879
+ message: "Internal error while waiting for interop finalization.",
11880
+ ctx: { where: "interop.wait" }
11881
+ });
11882
+ const tryWait = (dstChain, h, opts) => toResult2(OP_INTEROP.tryWait, () => wait(dstChain, h, opts));
11883
+ const finalize = (dstChain, h, opts) => wrap7(
11616
11884
  OP_INTEROP.finalize,
11617
11885
  async () => {
11886
+ const dstProvider = resolveChainRef(dstChain);
11618
11887
  if (isInteropFinalizationInfo(h)) {
11619
- if (h.dstChain == null) {
11620
- throw createError("STATE", {
11621
- resource: "interop",
11622
- operation: OP_INTEROP.finalize,
11623
- message: "Missing dstChain in interop finalization info.",
11624
- context: { input: h }
11625
- });
11626
- }
11627
- const dstProvider2 = resolveDstProvider(h.dstChain);
11628
- return svc.finalize(dstProvider2, h, opts);
11888
+ return svc.finalize(dstProvider, h, opts);
11629
11889
  }
11630
- const { dstProvider, waitable } = resolveWaitableInput(h);
11631
- const info = await svc.wait(dstProvider, waitable);
11890
+ const info = await svc.wait(dstProvider, getGwProvider(), h);
11632
11891
  return svc.finalize(dstProvider, info, opts);
11633
11892
  },
11634
11893
  {
@@ -11636,7 +11895,7 @@ function createInteropResource(client, tokens, contracts, attributes) {
11636
11895
  ctx: { where: "interop.finalize" }
11637
11896
  }
11638
11897
  );
11639
- const tryFinalize = (h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(h, opts));
11898
+ const tryFinalize = (dstChain, h, opts) => toResult2(OP_INTEROP.tryFinalize, () => finalize(dstChain, h, opts));
11640
11899
  return {
11641
11900
  quote,
11642
11901
  tryQuote,
@@ -11653,10 +11912,10 @@ function createInteropResource(client, tokens, contracts, attributes) {
11653
11912
  }
11654
11913
 
11655
11914
  // src/adapters/ethers/sdk.ts
11656
- function createEthersSdk(client) {
11915
+ function createEthersSdk(client, options) {
11657
11916
  const tokens = createTokensResource(client);
11658
11917
  const contracts = createContractsResource(client);
11659
- const interop = createInteropResource(client);
11918
+ const interop = createInteropResource(client, options?.interop, tokens, contracts);
11660
11919
  return {
11661
11920
  deposits: createDepositsResource(client, tokens, contracts),
11662
11921
  withdrawals: createWithdrawalsResource(client, tokens, contracts),