@matterlabs/zksync-js 0.0.2 → 0.0.5

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 (61) hide show
  1. package/README.md +1 -3
  2. package/dist/adapters/ethers/client.cjs.map +1 -1
  3. package/dist/adapters/ethers/index.cjs +391 -170
  4. package/dist/adapters/ethers/index.cjs.map +1 -1
  5. package/dist/adapters/ethers/index.d.ts +1 -0
  6. package/dist/adapters/ethers/index.js +3 -3
  7. package/dist/adapters/ethers/resources/contracts/contracts.d.ts +9 -0
  8. package/dist/adapters/ethers/resources/contracts/index.d.ts +2 -0
  9. package/dist/adapters/ethers/resources/contracts/types.d.ts +60 -0
  10. package/dist/adapters/ethers/resources/deposits/context.d.ts +16 -2
  11. package/dist/adapters/ethers/resources/deposits/index.d.ts +3 -1
  12. package/dist/adapters/ethers/resources/deposits/services/gas.d.ts +3 -2
  13. package/dist/adapters/ethers/resources/tokens/index.d.ts +1 -0
  14. package/dist/adapters/ethers/resources/tokens/tokens.d.ts +10 -0
  15. package/dist/adapters/ethers/resources/utils.d.ts +0 -3
  16. package/dist/adapters/ethers/resources/withdrawals/context.d.ts +11 -3
  17. package/dist/adapters/ethers/resources/withdrawals/index.d.ts +3 -1
  18. package/dist/adapters/ethers/sdk.cjs +386 -154
  19. package/dist/adapters/ethers/sdk.cjs.map +1 -1
  20. package/dist/adapters/ethers/sdk.d.ts +5 -22
  21. package/dist/adapters/ethers/sdk.js +3 -3
  22. package/dist/adapters/viem/client.cjs.map +1 -1
  23. package/dist/adapters/viem/index.cjs +383 -176
  24. package/dist/adapters/viem/index.cjs.map +1 -1
  25. package/dist/adapters/viem/index.d.ts +3 -0
  26. package/dist/adapters/viem/index.js +3 -3
  27. package/dist/adapters/viem/resources/contracts/contracts.d.ts +9 -0
  28. package/dist/adapters/viem/resources/contracts/index.d.ts +2 -0
  29. package/dist/adapters/viem/resources/contracts/types.d.ts +61 -0
  30. package/dist/adapters/viem/resources/deposits/context.d.ts +16 -2
  31. package/dist/adapters/viem/resources/deposits/index.d.ts +3 -1
  32. package/dist/adapters/viem/resources/deposits/services/gas.d.ts +2 -1
  33. package/dist/adapters/viem/resources/tokens/index.d.ts +1 -0
  34. package/dist/adapters/viem/resources/tokens/tokens.d.ts +3 -0
  35. package/dist/adapters/viem/resources/utils.d.ts +0 -3
  36. package/dist/adapters/viem/resources/withdrawals/context.d.ts +11 -3
  37. package/dist/adapters/viem/resources/withdrawals/index.d.ts +3 -1
  38. package/dist/adapters/viem/sdk.cjs +401 -189
  39. package/dist/adapters/viem/sdk.cjs.map +1 -1
  40. package/dist/adapters/viem/sdk.d.ts +5 -25
  41. package/dist/adapters/viem/sdk.js +3 -3
  42. package/dist/{chunk-OC6ZVLSP.js → chunk-JXUFGIJG.js} +348 -150
  43. package/dist/{chunk-QJS6ETEE.js → chunk-LL3WKCFJ.js} +15 -1
  44. package/dist/{chunk-BCCKWWOX.js → chunk-NBJEQAOE.js} +373 -158
  45. package/dist/{chunk-HLUANWGN.js → chunk-NEC2ZKHI.js} +4 -12
  46. package/dist/chunk-NTEIA5KA.js +13 -0
  47. package/dist/core/codec/ntv.d.ts +48 -0
  48. package/dist/core/index.cjs +4 -0
  49. package/dist/core/index.cjs.map +1 -1
  50. package/dist/core/index.d.ts +1 -0
  51. package/dist/core/index.js +2 -1
  52. package/dist/core/types/errors.d.ts +1 -1
  53. package/dist/core/types/flows/token.d.ts +192 -0
  54. package/dist/core/utils/addr.d.ts +2 -0
  55. package/dist/index.cjs +4 -0
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.js +2 -1
  59. package/package.json +1 -1
  60. package/dist/adapters/ethers/resources/token-info.d.ts +0 -31
  61. package/dist/adapters/viem/resources/token-info.d.ts +0 -34
@@ -1,21 +1,39 @@
1
- import { buildFeeBreakdown, quoteL2Gas, quoteL1Gas, quoteL2Gas2 } from './chunk-QJS6ETEE.js';
2
- import { findL1MessageSentLog, messengerLogIndex, isAddressEq, isHash66, pickDepositRoute, isETH, normalizeAddrEq, pickWithdrawRoute } from './chunk-HLUANWGN.js';
1
+ import { createNTVCodec, buildFeeBreakdown, quoteL2Gas, quoteL1Gas, quoteL2Gas2 } from './chunk-LL3WKCFJ.js';
2
+ import { findL1MessageSentLog, messengerLogIndex, normalizeL1Token, isAddressEq, hexEq, isHash66, isETH, normalizeAddrEq, pickWithdrawRoute } from './chunk-NEC2ZKHI.js';
3
3
  import { REVERT_TO_READINESS } from './chunk-NCAIVYBR.js';
4
4
  import { IL1Nullifier_default, IERC20_default, L1NativeTokenVault_default, L2NativeTokenVault_default, Mailbox_default, isZKsyncError, createError, shapeCause, OP_WITHDRAWALS, OP_DEPOSITS, isReceiptNotFound, IBridgehub_default, IL2AssetRouter_default, IBaseToken_default } from './chunk-M5J2MM2U.js';
5
- import { ETH_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, L1_MESSENGER_ADDRESS, L2_ASSET_ROUTER_ADDRESS, FORMAL_ETH_ADDRESS, L2_BASE_TOKEN_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, SAFE_L1_BRIDGE_GAS } from './chunk-F2ENUV3A.js';
6
- import { encodeAbiParameters, keccak256, concat, decodeErrorResult, decodeAbiParameters, decodeEventLog, encodeFunctionData, zeroAddress } from 'viem';
5
+ import { ETH_ADDRESS, L1_MESSENGER_ADDRESS, L2_ASSET_ROUTER_ADDRESS, L2_BASE_TOKEN_ADDRESS, L2_NATIVE_TOKEN_VAULT_ADDRESS, TOPIC_CANONICAL_ASSIGNED, TOPIC_CANONICAL_SUCCESS, SAFE_L1_BRIDGE_GAS } from './chunk-F2ENUV3A.js';
6
+ import { keccak256, encodeAbiParameters, concat, decodeErrorResult, decodeAbiParameters, decodeEventLog, encodeFunctionData, zeroAddress } from 'viem';
7
7
 
8
8
  // src/adapters/viem/resources/deposits/context.ts
9
- async function commonCtx(p, client) {
10
- const { bridgehub, l1AssetRouter } = await client.ensureAddresses();
9
+ async function commonCtx(p, client, tokens, contracts) {
10
+ const { bridgehub, l1AssetRouter } = await contracts.addresses();
11
11
  const chainId = await client.l2.getChainId();
12
12
  const sender = client.account.address;
13
13
  const gasPerPubdata = p.gasPerPubdata ?? 800n;
14
14
  const operatorTip = p.operatorTip ?? 0n;
15
15
  const refundRecipient = p.refundRecipient ?? sender;
16
- const route = await pickDepositRoute(client, BigInt(chainId), p.token);
16
+ const resolvedToken = await tokens.resolve(p.token, { chain: "l1" });
17
+ const baseTokenAssetId = resolvedToken.baseTokenAssetId;
18
+ const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
19
+ const baseIsEth = resolvedToken.isChainEthBased;
20
+ const route = (() => {
21
+ if (resolvedToken.kind === "eth") {
22
+ return baseIsEth ? "eth-base" : "eth-nonbase";
23
+ }
24
+ if (resolvedToken.kind === "base") {
25
+ return baseIsEth ? "eth-base" : "erc20-base";
26
+ }
27
+ return "erc20-nonbase";
28
+ })();
17
29
  return {
18
30
  client,
31
+ tokens,
32
+ contracts,
33
+ resolvedToken,
34
+ baseTokenAssetId,
35
+ baseTokenL1,
36
+ baseIsEth,
19
37
  l1AssetRouter,
20
38
  route,
21
39
  bridgehub,
@@ -28,17 +46,6 @@ async function commonCtx(p, client) {
28
46
  refundRecipient
29
47
  };
30
48
  }
31
- function encodeNativeTokenVaultAssetId(chainId, address) {
32
- const encoded = encodeAbiParameters(
33
- [
34
- { type: "uint256", name: "originChainId" },
35
- { type: "address", name: "ntv" },
36
- { type: "address", name: "token" }
37
- ],
38
- [chainId, L2_NATIVE_TOKEN_VAULT_ADDRESS, address]
39
- );
40
- return keccak256(encoded);
41
- }
42
49
  function encodeNativeTokenVaultTransferData(amount, receiver, token) {
43
50
  return encodeAbiParameters(
44
51
  [
@@ -59,8 +66,6 @@ function encodeSecondBridgeDataV1(assetId, transferData) {
59
66
  );
60
67
  return concat(["0x01", data]);
61
68
  }
62
- var encodeNTVAssetId = encodeNativeTokenVaultAssetId;
63
- var encodeNTVTransferData = encodeNativeTokenVaultTransferData;
64
69
  function encodeSecondBridgeArgs(token, amount, l2Receiver) {
65
70
  return encodeAbiParameters(
66
71
  [
@@ -218,7 +223,7 @@ function createErrorHandlers(resource) {
218
223
  function wrap2(operation, fn, opts) {
219
224
  return run("INTERNAL", operation, fn, opts);
220
225
  }
221
- function wrapAs9(kind, operation, fn, opts) {
226
+ function wrapAs10(kind, operation, fn, opts) {
222
227
  return run(kind, operation, fn, opts);
223
228
  }
224
229
  async function toResult2(operation, fn, opts) {
@@ -239,7 +244,7 @@ function createErrorHandlers(resource) {
239
244
  return { ok: false, error: shaped };
240
245
  }
241
246
  }
242
- return { wrap: wrap2, wrapAs: wrapAs9, toResult: toResult2 };
247
+ return { wrap: wrap2, wrapAs: wrapAs10, toResult: toResult2 };
243
248
  }
244
249
 
245
250
  // src/adapters/viem/estimator.ts
@@ -360,13 +365,7 @@ async function determineErc20L2Gas(input) {
360
365
  });
361
366
  }
362
367
  try {
363
- const l2NativeTokenVault = (await ctx.client.contracts()).l2NativeTokenVault;
364
- const l2TokenAddress = await ctx.client.l2.readContract({
365
- address: l2NativeTokenVault.address,
366
- abi: l2NativeTokenVault.abi,
367
- functionName: "l2TokenAddress",
368
- args: [l1Token]
369
- });
368
+ const l2TokenAddress = ctx.tokens ? await ctx.tokens.toL2Address(l1Token) : await (await ctx.contracts.l2NativeTokenVault()).read.l2TokenAddress([l1Token]);
370
369
  if (l2TokenAddress === zeroAddress) {
371
370
  return quoteL2Gas3({
372
371
  ctx,
@@ -529,18 +528,18 @@ function routeErc20NonBase() {
529
528
  "VALIDATION",
530
529
  OP_DEPOSITS.nonbase.assertNotEthAsset,
531
530
  () => {
532
- if (isETH(p.token)) {
531
+ if (ctx.resolvedToken?.kind === "eth" || isETH(p.token)) {
533
532
  throw new Error("erc20-nonbase route requires an ERC-20 token (not ETH).");
534
533
  }
535
534
  },
536
535
  { ctx: { token: p.token } }
537
536
  );
538
- const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
537
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
539
538
  await wrapAs3(
540
539
  "VALIDATION",
541
540
  OP_DEPOSITS.nonbase.assertNonBaseToken,
542
541
  () => {
543
- if (normalizeAddrEq(baseToken, p.token)) {
542
+ if (ctx.resolvedToken?.kind === "base" || normalizeAddrEq(baseToken, p.token)) {
544
543
  throw new Error("erc20-nonbase route requires a non-base ERC-20 deposit token.");
545
544
  }
546
545
  },
@@ -548,8 +547,8 @@ function routeErc20NonBase() {
548
547
  );
549
548
  },
550
549
  async build(p, ctx) {
551
- const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
552
- const baseIsEth = isETH(baseToken);
550
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
551
+ const baseIsEth = ctx.baseIsEth ?? isETH(baseToken);
553
552
  const assetRouter = ctx.l1AssetRouter;
554
553
  const l2Gas = await determineErc20L2Gas({
555
554
  ctx,
@@ -756,22 +755,21 @@ function routeEthNonBase() {
756
755
  "VALIDATION",
757
756
  OP_DEPOSITS.ethNonBase.assertEthAsset,
758
757
  () => {
759
- if (!isETH(p.token)) {
758
+ if (ctx.resolvedToken?.kind !== "eth" && !isETH(p.token)) {
760
759
  throw new Error("eth-nonbase route requires ETH as the deposit asset.");
761
760
  }
762
761
  },
763
762
  { ctx: { token: p.token } }
764
763
  );
765
- const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
766
764
  await wrapAs4(
767
765
  "VALIDATION",
768
766
  OP_DEPOSITS.ethNonBase.assertNonEthBase,
769
767
  () => {
770
- if (isETH(baseToken)) {
768
+ if (ctx.baseIsEth) {
771
769
  throw new Error("eth-nonbase route requires target chain base token \u2260 ETH.");
772
770
  }
773
771
  },
774
- { ctx: { baseToken, chainIdL2: ctx.chainIdL2 } }
772
+ { ctx: { baseIsEth: ctx.baseIsEth, chainIdL2: ctx.chainIdL2 } }
775
773
  );
776
774
  const ethBal = await wrapAs4(
777
775
  "RPC",
@@ -794,7 +792,7 @@ function routeEthNonBase() {
794
792
  );
795
793
  },
796
794
  async build(p, ctx) {
797
- const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
795
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
798
796
  const l2TxModel = {
799
797
  to: p.to ?? ctx.sender,
800
798
  from: ctx.sender,
@@ -967,13 +965,13 @@ function routeErc20Base() {
967
965
  "VALIDATION",
968
966
  OP_DEPOSITS.base.assertErc20Asset,
969
967
  () => {
970
- if (isETH(p.token)) {
968
+ if (ctx.resolvedToken?.kind === "eth" || isETH(p.token)) {
971
969
  throw new Error("erc20-base route requires an ERC-20 token (not ETH).");
972
970
  }
973
971
  },
974
972
  { ctx: { token: p.token } }
975
973
  );
976
- const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
974
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
977
975
  await wrapAs5(
978
976
  "VALIDATION",
979
977
  OP_DEPOSITS.base.assertMatchesBase,
@@ -986,7 +984,7 @@ function routeErc20Base() {
986
984
  );
987
985
  },
988
986
  async build(p, ctx) {
989
- const baseToken = await ctx.client.baseToken(ctx.chainIdL2);
987
+ const baseToken = ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2);
990
988
  const l2TxModel = {
991
989
  to: p.to ?? ctx.sender,
992
990
  from: ctx.sender,
@@ -1211,6 +1209,260 @@ async function waitForL2ExecutionFromL1Tx(l1, l2, l1TxHash) {
1211
1209
  }
1212
1210
  return { l2Receipt, l2TxHash };
1213
1211
  }
1212
+ var { wrapAs: wrapAs6 } = createErrorHandlers("tokens");
1213
+ var ntvCodec = createNTVCodec({
1214
+ encode: (types, values) => encodeAbiParameters(
1215
+ types.map((t, i) => ({ type: t, name: `arg${i}` })),
1216
+ values
1217
+ ),
1218
+ keccak256: (data) => keccak256(data)
1219
+ });
1220
+ function createTokensResource(client) {
1221
+ let l2NtvL1ChainIdPromise = null;
1222
+ let baseTokenAssetIdPromise = null;
1223
+ let wethL1Promise = null;
1224
+ let wethL2Promise = null;
1225
+ async function getL1ChainId() {
1226
+ if (!l2NtvL1ChainIdPromise) {
1227
+ l2NtvL1ChainIdPromise = wrapAs6("INTERNAL", "getL1ChainId", async () => {
1228
+ const { l2NativeTokenVault } = await client.contracts();
1229
+ return await l2NativeTokenVault.read.L1_CHAIN_ID();
1230
+ });
1231
+ }
1232
+ return l2NtvL1ChainIdPromise;
1233
+ }
1234
+ async function getBaseTokenAssetId() {
1235
+ if (!baseTokenAssetIdPromise) {
1236
+ baseTokenAssetIdPromise = wrapAs6("INTERNAL", "baseTokenAssetId", async () => {
1237
+ const { l2NativeTokenVault } = await client.contracts();
1238
+ const assetId = await l2NativeTokenVault.read.BASE_TOKEN_ASSET_ID();
1239
+ return assetId;
1240
+ });
1241
+ }
1242
+ return baseTokenAssetIdPromise;
1243
+ }
1244
+ async function getWethL1() {
1245
+ if (!wethL1Promise) {
1246
+ wethL1Promise = wrapAs6("INTERNAL", "wethL1", async () => {
1247
+ const { l1NativeTokenVault } = await client.contracts();
1248
+ const weth = await l1NativeTokenVault.read.WETH_TOKEN();
1249
+ return weth;
1250
+ });
1251
+ }
1252
+ return wethL1Promise;
1253
+ }
1254
+ async function getWethL2() {
1255
+ if (!wethL2Promise) {
1256
+ wethL2Promise = wrapAs6("INTERNAL", "wethL2", async () => {
1257
+ const { l2NativeTokenVault } = await client.contracts();
1258
+ const weth = await l2NativeTokenVault.read.WETH_TOKEN();
1259
+ return weth;
1260
+ });
1261
+ }
1262
+ return wethL2Promise;
1263
+ }
1264
+ async function toL2Address(l1Token) {
1265
+ return wrapAs6("CONTRACT", "tokens.toL2Address", async () => {
1266
+ const normalized = normalizeL1Token(l1Token);
1267
+ const chainId = BigInt(await client.l2.getChainId());
1268
+ const baseToken = await client.baseToken(chainId);
1269
+ if (isAddressEq(normalized, baseToken)) {
1270
+ return L2_BASE_TOKEN_ADDRESS;
1271
+ }
1272
+ const { l2NativeTokenVault } = await client.contracts();
1273
+ const l2Token = await l2NativeTokenVault.read.l2TokenAddress([normalized]);
1274
+ return l2Token;
1275
+ });
1276
+ }
1277
+ async function toL1Address(l2Token) {
1278
+ return wrapAs6("CONTRACT", "tokens.toL1Address", async () => {
1279
+ if (isAddressEq(l2Token, ETH_ADDRESS)) return ETH_ADDRESS;
1280
+ if (isAddressEq(l2Token, L2_BASE_TOKEN_ADDRESS)) {
1281
+ const chainId = BigInt(await client.l2.getChainId());
1282
+ return await client.baseToken(chainId);
1283
+ }
1284
+ const { l2AssetRouter } = await client.contracts();
1285
+ const l1Token = await l2AssetRouter.read.l1TokenAddress([l2Token]);
1286
+ return l1Token;
1287
+ });
1288
+ }
1289
+ async function assetIdOfL1(l1Token) {
1290
+ return wrapAs6("CONTRACT", "tokens.assetIdOfL1", async () => {
1291
+ const normalized = normalizeL1Token(l1Token);
1292
+ const { l1NativeTokenVault } = await client.contracts();
1293
+ return await l1NativeTokenVault.read.assetId([normalized]);
1294
+ });
1295
+ }
1296
+ async function assetIdOfL2(l2Token) {
1297
+ return wrapAs6("CONTRACT", "tokens.assetIdOfL2", async () => {
1298
+ const { l2NativeTokenVault } = await client.contracts();
1299
+ return await l2NativeTokenVault.read.assetId([l2Token]);
1300
+ });
1301
+ }
1302
+ async function l2TokenFromAssetId(assetId) {
1303
+ return wrapAs6("CONTRACT", "tokens.l2TokenFromAssetId", async () => {
1304
+ const { l2NativeTokenVault } = await client.contracts();
1305
+ return await l2NativeTokenVault.read.tokenAddress([assetId]);
1306
+ });
1307
+ }
1308
+ async function l1TokenFromAssetId(assetId) {
1309
+ return wrapAs6("CONTRACT", "tokens.l1TokenFromAssetId", async () => {
1310
+ const { l1NativeTokenVault } = await client.contracts();
1311
+ return await l1NativeTokenVault.read.tokenAddress([assetId]);
1312
+ });
1313
+ }
1314
+ async function originChainId(assetId) {
1315
+ return wrapAs6("CONTRACT", "tokens.originChainId", async () => {
1316
+ const { l2NativeTokenVault } = await client.contracts();
1317
+ return await l2NativeTokenVault.read.originChainId([assetId]);
1318
+ });
1319
+ }
1320
+ async function baseTokenAssetId() {
1321
+ return getBaseTokenAssetId();
1322
+ }
1323
+ async function isChainEthBased() {
1324
+ return wrapAs6("CONTRACT", "tokens.isChainEthBased", async () => {
1325
+ const baseAssetId = await getBaseTokenAssetId();
1326
+ const l1ChainId = await getL1ChainId();
1327
+ const ethAssetId = ntvCodec.encodeAssetId(
1328
+ l1ChainId,
1329
+ L2_NATIVE_TOKEN_VAULT_ADDRESS,
1330
+ ETH_ADDRESS
1331
+ );
1332
+ return hexEq(baseAssetId, ethAssetId);
1333
+ });
1334
+ }
1335
+ async function wethL1() {
1336
+ return getWethL1();
1337
+ }
1338
+ async function wethL2() {
1339
+ return getWethL2();
1340
+ }
1341
+ async function computeL2BridgedAddress(args) {
1342
+ return wrapAs6("CONTRACT", "tokens.computeL2BridgedAddress", async () => {
1343
+ const normalized = normalizeL1Token(args.l1Token);
1344
+ const { l2NativeTokenVault } = await client.contracts();
1345
+ const predicted = await l2NativeTokenVault.read.calculateCreate2TokenAddress([
1346
+ args.originChainId,
1347
+ normalized
1348
+ ]);
1349
+ return predicted;
1350
+ });
1351
+ }
1352
+ async function resolve(ref, opts) {
1353
+ return wrapAs6("CONTRACT", "tokens.resolve", async () => {
1354
+ let chain;
1355
+ let address;
1356
+ if (typeof ref === "string") {
1357
+ chain = opts?.chain ?? "l1";
1358
+ address = ref;
1359
+ } else {
1360
+ chain = ref.chain;
1361
+ address = ref.address;
1362
+ }
1363
+ let l1;
1364
+ let l2;
1365
+ if (chain === "l1") {
1366
+ l1 = normalizeL1Token(address);
1367
+ l2 = await toL2Address(address);
1368
+ } else {
1369
+ l2 = address;
1370
+ l1 = await toL1Address(address);
1371
+ }
1372
+ const assetId = await assetIdOfL1(l1);
1373
+ const originChainIdVal = await originChainId(assetId);
1374
+ const [baseAssetId, wethL1Addr, wethL2Addr, ethBased] = await Promise.all([
1375
+ baseTokenAssetId(),
1376
+ wethL1(),
1377
+ wethL2(),
1378
+ isChainEthBased()
1379
+ ]);
1380
+ let kind;
1381
+ if (isAddressEq(l1, ETH_ADDRESS)) {
1382
+ kind = "eth";
1383
+ } else if (hexEq(assetId, baseAssetId)) {
1384
+ kind = "base";
1385
+ } else {
1386
+ kind = "erc20";
1387
+ }
1388
+ return {
1389
+ kind,
1390
+ l1,
1391
+ l2,
1392
+ assetId,
1393
+ originChainId: originChainIdVal,
1394
+ isChainEthBased: ethBased,
1395
+ baseTokenAssetId: baseAssetId,
1396
+ wethL1: wethL1Addr,
1397
+ wethL2: wethL2Addr
1398
+ };
1399
+ });
1400
+ }
1401
+ return {
1402
+ resolve,
1403
+ toL2Address,
1404
+ toL1Address,
1405
+ assetIdOfL1,
1406
+ assetIdOfL2,
1407
+ l2TokenFromAssetId,
1408
+ l1TokenFromAssetId,
1409
+ originChainId,
1410
+ baseTokenAssetId,
1411
+ isChainEthBased,
1412
+ wethL1,
1413
+ wethL2,
1414
+ computeL2BridgedAddress
1415
+ };
1416
+ }
1417
+
1418
+ // src/adapters/viem/resources/contracts/contracts.ts
1419
+ function createContractsResource(client) {
1420
+ async function addresses() {
1421
+ return client.ensureAddresses();
1422
+ }
1423
+ async function instances() {
1424
+ return client.contracts();
1425
+ }
1426
+ async function bridgehub() {
1427
+ const { bridgehub: bridgehub2 } = await instances();
1428
+ return bridgehub2;
1429
+ }
1430
+ async function l1AssetRouter() {
1431
+ const { l1AssetRouter: l1AssetRouter2 } = await instances();
1432
+ return l1AssetRouter2;
1433
+ }
1434
+ async function l1NativeTokenVault() {
1435
+ const { l1NativeTokenVault: l1NativeTokenVault2 } = await instances();
1436
+ return l1NativeTokenVault2;
1437
+ }
1438
+ async function l1Nullifier() {
1439
+ const { l1Nullifier: l1Nullifier2 } = await instances();
1440
+ return l1Nullifier2;
1441
+ }
1442
+ async function l2AssetRouter() {
1443
+ const { l2AssetRouter: l2AssetRouter2 } = await instances();
1444
+ return l2AssetRouter2;
1445
+ }
1446
+ async function l2NativeTokenVault() {
1447
+ const { l2NativeTokenVault: l2NativeTokenVault2 } = await instances();
1448
+ return l2NativeTokenVault2;
1449
+ }
1450
+ async function l2BaseTokenSystem() {
1451
+ const { l2BaseTokenSystem: l2BaseTokenSystem2 } = await instances();
1452
+ return l2BaseTokenSystem2;
1453
+ }
1454
+ return {
1455
+ addresses,
1456
+ instances,
1457
+ bridgehub,
1458
+ l1AssetRouter,
1459
+ l1NativeTokenVault,
1460
+ l1Nullifier,
1461
+ l2AssetRouter,
1462
+ l2NativeTokenVault,
1463
+ l2BaseTokenSystem
1464
+ };
1465
+ }
1214
1466
 
1215
1467
  // src/adapters/viem/resources/deposits/index.ts
1216
1468
  var { wrap, toResult } = createErrorHandlers("deposits");
@@ -1220,9 +1472,11 @@ var ROUTES = {
1220
1472
  "erc20-nonbase": routeErc20NonBase(),
1221
1473
  "erc20-base": routeErc20Base()
1222
1474
  };
1223
- function createDepositsResource(client) {
1475
+ function createDepositsResource(client, tokens, contracts) {
1476
+ const tokensResource = tokens ?? createTokensResource(client);
1477
+ const contractsResource = contracts ?? createContractsResource(client);
1224
1478
  async function buildPlan(p) {
1225
- const ctx = await commonCtx(p, client);
1479
+ const ctx = await commonCtx(p, client, tokensResource, contractsResource);
1226
1480
  const route = ctx.route;
1227
1481
  await ROUTES[route].preflight?.(p, ctx);
1228
1482
  const { steps, approvals, fees } = await ROUTES[route].build(p, ctx);
@@ -1526,32 +1780,8 @@ function createDepositsResource(client) {
1526
1780
  return { quote, tryQuote, prepare, tryPrepare, create, tryCreate, status, wait, tryWait };
1527
1781
  }
1528
1782
 
1529
- // src/adapters/viem/resources/token-info.ts
1530
- async function ntvBaseAssetId(l2, ntv) {
1531
- return l2.readContract({
1532
- address: ntv,
1533
- abi: L2NativeTokenVault_default,
1534
- functionName: "BASE_TOKEN_ASSET_ID"
1535
- });
1536
- }
1537
- async function ntvL1ChainId(l2, ntv) {
1538
- return l2.readContract({
1539
- address: ntv,
1540
- abi: L2NativeTokenVault_default,
1541
- functionName: "L1_CHAIN_ID"
1542
- });
1543
- }
1544
- async function isEthBasedChain(l2, ntv) {
1545
- const [baseAssetId, l1ChainId] = await Promise.all([
1546
- ntvBaseAssetId(l2, ntv),
1547
- ntvL1ChainId(l2, ntv)
1548
- ]);
1549
- const ethAssetId = encodeNativeTokenVaultAssetId(l1ChainId, ETH_ADDRESS);
1550
- return baseAssetId.toLowerCase() === ethAssetId.toLowerCase();
1551
- }
1552
-
1553
1783
  // src/adapters/viem/resources/withdrawals/context.ts
1554
- async function commonCtx2(p, client) {
1784
+ async function commonCtx2(p, client, tokens, contracts) {
1555
1785
  const sender = client.account.address;
1556
1786
  const {
1557
1787
  bridgehub,
@@ -1560,12 +1790,20 @@ async function commonCtx2(p, client) {
1560
1790
  l2AssetRouter,
1561
1791
  l2NativeTokenVault,
1562
1792
  l2BaseTokenSystem
1563
- } = await client.ensureAddresses();
1793
+ } = await contracts.addresses();
1564
1794
  const chainIdL2 = BigInt(await client.l2.getChainId());
1565
- const baseIsEth = await isEthBasedChain(client.l2, l2NativeTokenVault);
1795
+ const resolvedToken = await tokens.resolve(p.token, { chain: "l2" });
1796
+ const baseTokenAssetId = resolvedToken.baseTokenAssetId;
1797
+ const baseTokenL1 = await tokens.l1TokenFromAssetId(baseTokenAssetId);
1798
+ const baseIsEth = resolvedToken.isChainEthBased;
1566
1799
  const route = pickWithdrawRoute({ token: p.token, baseIsEth });
1567
1800
  return {
1568
1801
  client,
1802
+ tokens,
1803
+ contracts,
1804
+ resolvedToken,
1805
+ baseTokenAssetId,
1806
+ baseTokenL1,
1569
1807
  bridgehub,
1570
1808
  chainIdL2,
1571
1809
  sender,
@@ -1608,12 +1846,12 @@ function buildFeeBreakdown2(p) {
1608
1846
  }
1609
1847
 
1610
1848
  // src/adapters/viem/resources/withdrawals/routes/eth.ts
1611
- var { wrapAs: wrapAs6 } = createErrorHandlers("withdrawals");
1849
+ var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
1612
1850
  function routeEthBase() {
1613
1851
  return {
1614
1852
  async build(p, ctx) {
1615
1853
  const steps = [];
1616
- const data = await wrapAs6(
1854
+ const data = await wrapAs7(
1617
1855
  "INTERNAL",
1618
1856
  OP_WITHDRAWALS.eth.encodeWithdraw,
1619
1857
  () => Promise.resolve(
@@ -1663,14 +1901,14 @@ function routeEthBase() {
1663
1901
  }
1664
1902
  };
1665
1903
  }
1666
- var { wrapAs: wrapAs7 } = createErrorHandlers("withdrawals");
1904
+ var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
1667
1905
  function routeErc20NonBase2() {
1668
1906
  return {
1669
1907
  // TODO: add preflight validations here
1670
1908
  async build(p, ctx) {
1671
1909
  const steps = [];
1672
1910
  const approvals = [];
1673
- const current = await wrapAs7(
1911
+ const current = await wrapAs8(
1674
1912
  "CONTRACT",
1675
1913
  OP_WITHDRAWALS.erc20.allowance,
1676
1914
  () => ctx.client.l2.readContract({
@@ -1709,7 +1947,7 @@ function routeErc20NonBase2() {
1709
1947
  approveTxCandidate.maxFeePerGas = approveGas.maxFeePerGas;
1710
1948
  approveTxCandidate.maxPriorityFeePerGas = approveGas.maxPriorityFeePerGas;
1711
1949
  }
1712
- const approveSim = await wrapAs7(
1950
+ const approveSim = await wrapAs8(
1713
1951
  "CONTRACT",
1714
1952
  OP_WITHDRAWALS.erc20.estGas,
1715
1953
  () => ctx.client.l2.simulateContract({
@@ -1736,7 +1974,8 @@ function routeErc20NonBase2() {
1736
1974
  tx: approveTx
1737
1975
  });
1738
1976
  }
1739
- const ensure = await wrapAs7(
1977
+ const resolved = ctx.resolvedToken ?? (ctx.tokens ? await ctx.tokens.resolve(p.token, { chain: "l2" }) : void 0);
1978
+ const assetId = resolved?.assetId ?? (await wrapAs8(
1740
1979
  "CONTRACT",
1741
1980
  OP_WITHDRAWALS.erc20.ensureRegistered,
1742
1981
  () => ctx.client.l2.simulateContract({
@@ -1750,8 +1989,7 @@ function routeErc20NonBase2() {
1750
1989
  ctx: { where: "L2NativeTokenVault.ensureTokenIsRegistered", token: p.token },
1751
1990
  message: "Failed to ensure token is registered in L2NativeTokenVault."
1752
1991
  }
1753
- );
1754
- const assetId = ensure.result;
1992
+ )).result;
1755
1993
  const assetData = encodeAbiParameters(
1756
1994
  [
1757
1995
  { type: "uint256", name: "amount" },
@@ -1788,7 +2026,7 @@ function routeErc20NonBase2() {
1788
2026
  ...withdrawGas
1789
2027
  };
1790
2028
  } else {
1791
- const sim = await wrapAs7(
2029
+ const sim = await wrapAs8(
1792
2030
  "CONTRACT",
1793
2031
  OP_WITHDRAWALS.erc20.estGas,
1794
2032
  () => ctx.client.l2.simulateContract({
@@ -1817,14 +2055,14 @@ function routeErc20NonBase2() {
1817
2055
  tx: withdrawTx
1818
2056
  });
1819
2057
  const fees = buildFeeBreakdown2({
1820
- feeToken: await ctx.client.baseToken(ctx.chainIdL2),
2058
+ feeToken: ctx.baseTokenL1 ?? await ctx.client.baseToken(ctx.chainIdL2),
1821
2059
  l2Gas: withdrawGas
1822
2060
  });
1823
2061
  return { steps, approvals, fees };
1824
2062
  }
1825
2063
  };
1826
2064
  }
1827
- var { wrapAs: wrapAs8 } = createErrorHandlers("withdrawals");
2065
+ var { wrapAs: wrapAs9 } = createErrorHandlers("withdrawals");
1828
2066
  var IL1NullifierMini = [
1829
2067
  {
1830
2068
  type: "function",
@@ -1841,7 +2079,7 @@ var IL1NullifierMini = [
1841
2079
  function createFinalizationServices(client) {
1842
2080
  return {
1843
2081
  async fetchFinalizeDepositParams(l2TxHash) {
1844
- const parsed = await wrapAs8(
2082
+ const parsed = await wrapAs9(
1845
2083
  "RPC",
1846
2084
  OP_WITHDRAWALS.finalize.fetchParams.receipt,
1847
2085
  () => client.zks.getReceiptWithL2ToL1(l2TxHash),
@@ -1858,7 +2096,7 @@ function createFinalizationServices(client) {
1858
2096
  context: { l2TxHash }
1859
2097
  });
1860
2098
  }
1861
- const ev = await wrapAs8(
2099
+ const ev = await wrapAs9(
1862
2100
  "INTERNAL",
1863
2101
  OP_WITHDRAWALS.finalize.fetchParams.findMessage,
1864
2102
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
@@ -1868,7 +2106,7 @@ function createFinalizationServices(client) {
1868
2106
  message: "Failed to locate L1MessageSent event in L2 receipt."
1869
2107
  }
1870
2108
  );
1871
- const message = await wrapAs8(
2109
+ const message = await wrapAs9(
1872
2110
  "INTERNAL",
1873
2111
  OP_WITHDRAWALS.finalize.fetchParams.decodeMessage,
1874
2112
  () => {
@@ -1880,7 +2118,7 @@ function createFinalizationServices(client) {
1880
2118
  message: "Failed to decode withdrawal message."
1881
2119
  }
1882
2120
  );
1883
- const raw = await wrapAs8(
2121
+ const raw = await wrapAs9(
1884
2122
  "RPC",
1885
2123
  OP_WITHDRAWALS.finalize.fetchParams.rawReceipt,
1886
2124
  () => client.zks.getReceiptWithL2ToL1(l2TxHash),
@@ -1897,7 +2135,7 @@ function createFinalizationServices(client) {
1897
2135
  context: { l2TxHash }
1898
2136
  });
1899
2137
  }
1900
- const idx = await wrapAs8(
2138
+ const idx = await wrapAs9(
1901
2139
  "INTERNAL",
1902
2140
  OP_WITHDRAWALS.finalize.fetchParams.messengerIndex,
1903
2141
  () => Promise.resolve(messengerLogIndex(raw, { index: 0, messenger: L1_MESSENGER_ADDRESS })),
@@ -1906,7 +2144,7 @@ function createFinalizationServices(client) {
1906
2144
  message: "Failed to derive messenger log index."
1907
2145
  }
1908
2146
  );
1909
- const proof = await wrapAs8(
2147
+ const proof = await wrapAs9(
1910
2148
  "RPC",
1911
2149
  OP_WITHDRAWALS.finalize.fetchParams.proof,
1912
2150
  () => client.zks.getL2ToL1LogProof(l2TxHash, idx),
@@ -1915,7 +2153,7 @@ function createFinalizationServices(client) {
1915
2153
  message: "Failed to fetch L2\u2192L1 log proof."
1916
2154
  }
1917
2155
  );
1918
- const chainId = await wrapAs8(
2156
+ const chainId = await wrapAs9(
1919
2157
  "RPC",
1920
2158
  OP_WITHDRAWALS.finalize.fetchParams.network,
1921
2159
  () => client.l2.getChainId(),
@@ -1931,7 +2169,7 @@ function createFinalizationServices(client) {
1931
2169
  message,
1932
2170
  merkleProof: proof.proof
1933
2171
  };
1934
- const { l1Nullifier } = await wrapAs8(
2172
+ const { l1Nullifier } = await wrapAs9(
1935
2173
  "INTERNAL",
1936
2174
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
1937
2175
  () => client.ensureAddresses(),
@@ -1943,7 +2181,7 @@ function createFinalizationServices(client) {
1943
2181
  return { params, nullifier: l1Nullifier };
1944
2182
  },
1945
2183
  async simulateFinalizeReadiness(params) {
1946
- const { l1Nullifier } = await wrapAs8(
2184
+ const { l1Nullifier } = await wrapAs9(
1947
2185
  "INTERNAL",
1948
2186
  OP_WITHDRAWALS.finalize.readiness.ensureAddresses,
1949
2187
  () => client.ensureAddresses(),
@@ -1954,7 +2192,7 @@ function createFinalizationServices(client) {
1954
2192
  );
1955
2193
  const done = await (async () => {
1956
2194
  try {
1957
- const result = await wrapAs8(
2195
+ const result = await wrapAs9(
1958
2196
  "RPC",
1959
2197
  OP_WITHDRAWALS.finalize.readiness.isFinalized,
1960
2198
  () => client.l1.readContract({
@@ -1988,7 +2226,7 @@ function createFinalizationServices(client) {
1988
2226
  }
1989
2227
  },
1990
2228
  async isWithdrawalFinalized(key) {
1991
- const { l1Nullifier } = await wrapAs8(
2229
+ const { l1Nullifier } = await wrapAs9(
1992
2230
  "INTERNAL",
1993
2231
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
1994
2232
  () => client.ensureAddresses(),
@@ -1997,7 +2235,7 @@ function createFinalizationServices(client) {
1997
2235
  message: "Failed to ensure L1 Nullifier address."
1998
2236
  }
1999
2237
  );
2000
- return await wrapAs8(
2238
+ return await wrapAs9(
2001
2239
  "RPC",
2002
2240
  OP_WITHDRAWALS.finalize.isFinalized,
2003
2241
  () => client.l1.readContract({
@@ -2013,7 +2251,7 @@ function createFinalizationServices(client) {
2013
2251
  );
2014
2252
  },
2015
2253
  async estimateFinalization(params) {
2016
- const { l1Nullifier } = await wrapAs8(
2254
+ const { l1Nullifier } = await wrapAs9(
2017
2255
  "INTERNAL",
2018
2256
  OP_WITHDRAWALS.finalize.estimate,
2019
2257
  () => client.ensureAddresses(),
@@ -2022,7 +2260,7 @@ function createFinalizationServices(client) {
2022
2260
  message: "Failed to ensure L1 Nullifier address."
2023
2261
  }
2024
2262
  );
2025
- const gasLimit = await wrapAs8(
2263
+ const gasLimit = await wrapAs9(
2026
2264
  "RPC",
2027
2265
  OP_WITHDRAWALS.finalize.estimate,
2028
2266
  () => client.l1.estimateContractGas({
@@ -2046,7 +2284,7 @@ function createFinalizationServices(client) {
2046
2284
  let maxFeePerGas;
2047
2285
  let maxPriorityFeePerGas;
2048
2286
  try {
2049
- const fee = await wrapAs8(
2287
+ const fee = await wrapAs9(
2050
2288
  "RPC",
2051
2289
  OP_WITHDRAWALS.finalize.estimate,
2052
2290
  () => client.l1.estimateFeesPerGas(),
@@ -2065,7 +2303,7 @@ function createFinalizationServices(client) {
2065
2303
  })();
2066
2304
  maxPriorityFeePerGas = fee.maxPriorityFeePerGas ?? 0n;
2067
2305
  } catch {
2068
- const gasPrice = await wrapAs8(
2306
+ const gasPrice = await wrapAs9(
2069
2307
  "RPC",
2070
2308
  OP_WITHDRAWALS.finalize.estimate,
2071
2309
  () => client.l1.getGasPrice(),
@@ -2084,7 +2322,7 @@ function createFinalizationServices(client) {
2084
2322
  };
2085
2323
  },
2086
2324
  async finalizeDeposit(params) {
2087
- const { l1Nullifier } = await wrapAs8(
2325
+ const { l1Nullifier } = await wrapAs9(
2088
2326
  "INTERNAL",
2089
2327
  OP_WITHDRAWALS.finalize.fetchParams.ensureAddresses,
2090
2328
  () => client.ensureAddresses(),
@@ -2148,11 +2386,13 @@ var ROUTES2 = {
2148
2386
  "erc20-nonbase": routeErc20NonBase2()
2149
2387
  // AssetRouter.withdraw for non-base ERC-20s
2150
2388
  };
2151
- function createWithdrawalsResource(client) {
2389
+ function createWithdrawalsResource(client, tokens, contracts) {
2152
2390
  const svc = createFinalizationServices(client);
2153
2391
  const { wrap: wrap2, toResult: toResult2 } = createErrorHandlers("withdrawals");
2392
+ const tokensResource = tokens ?? createTokensResource(client);
2393
+ const contractsResource = contracts ?? createContractsResource(client);
2154
2394
  async function buildPlan(p) {
2155
- const ctx = await commonCtx2(p, client);
2395
+ const ctx = await commonCtx2(p, client, tokensResource, contractsResource);
2156
2396
  await ROUTES2[ctx.route].preflight?.(p, ctx);
2157
2397
  const { steps, approvals, fees } = await ROUTES2[ctx.route].build(p, ctx);
2158
2398
  return {
@@ -2499,56 +2739,14 @@ function createWithdrawalsResource(client) {
2499
2739
 
2500
2740
  // src/adapters/viem/sdk.ts
2501
2741
  function createViemSdk(client) {
2742
+ const tokens = createTokensResource(client);
2743
+ const contracts = createContractsResource(client);
2502
2744
  return {
2503
- deposits: createDepositsResource(client),
2504
- withdrawals: createWithdrawalsResource(client),
2505
- helpers: {
2506
- addresses: () => client.ensureAddresses(),
2507
- contracts: () => client.contracts(),
2508
- async l1AssetRouter() {
2509
- const { l1AssetRouter } = await client.contracts();
2510
- return l1AssetRouter;
2511
- },
2512
- async l1NativeTokenVault() {
2513
- const { l1NativeTokenVault } = await client.contracts();
2514
- return l1NativeTokenVault;
2515
- },
2516
- async l1Nullifier() {
2517
- const { l1Nullifier } = await client.contracts();
2518
- return l1Nullifier;
2519
- },
2520
- async baseToken(chainId) {
2521
- const id = chainId ?? BigInt(await client.l2.getChainId());
2522
- return client.baseToken(id);
2523
- },
2524
- async l2TokenAddress(l1Token) {
2525
- if (isAddressEq(l1Token, FORMAL_ETH_ADDRESS)) {
2526
- return ETH_ADDRESS;
2527
- }
2528
- const base = await client.baseToken(BigInt(await client.l2.getChainId()));
2529
- if (isAddressEq(l1Token, base)) {
2530
- return L2_BASE_TOKEN_ADDRESS;
2531
- }
2532
- const { l2NativeTokenVault } = await client.contracts();
2533
- const addr = await l2NativeTokenVault.read.l2TokenAddress([l1Token]);
2534
- return addr;
2535
- },
2536
- async l1TokenAddress(l2Token) {
2537
- if (isAddressEq(l2Token, FORMAL_ETH_ADDRESS)) {
2538
- return FORMAL_ETH_ADDRESS;
2539
- }
2540
- const { l2AssetRouter } = await client.contracts();
2541
- const addr = await l2AssetRouter.read.l1TokenAddress([l2Token]);
2542
- return addr;
2543
- },
2544
- async assetId(l1Token) {
2545
- const norm = isAddressEq(l1Token, FORMAL_ETH_ADDRESS) ? ETH_ADDRESS : l1Token;
2546
- const { l1NativeTokenVault } = await client.contracts();
2547
- const id = await l1NativeTokenVault.read.assetId([norm]);
2548
- return id;
2549
- }
2550
- }
2745
+ deposits: createDepositsResource(client, tokens, contracts),
2746
+ withdrawals: createWithdrawalsResource(client, tokens, contracts),
2747
+ tokens,
2748
+ contracts
2551
2749
  };
2552
2750
  }
2553
2751
 
2554
- export { buildDirectRequestStruct, classifyReadinessFromRevert, createDepositsResource, createErrorHandlers, createFinalizationServices, createViemSdk, createWithdrawalsResource, decodeRevert, encodeNTVAssetId, encodeNTVTransferData, encodeNativeTokenVaultAssetId, encodeNativeTokenVaultTransferData, encodeSecondBridgeArgs, encodeSecondBridgeDataV1, encodeSecondBridgeErc20Args, encodeSecondBridgeEthArgs, registerErrorAbi, toZKsyncError };
2752
+ export { buildDirectRequestStruct, classifyReadinessFromRevert, createContractsResource, createDepositsResource, createErrorHandlers, createFinalizationServices, createTokensResource, createViemSdk, createWithdrawalsResource, decodeRevert, encodeNativeTokenVaultTransferData, encodeSecondBridgeArgs, encodeSecondBridgeDataV1, encodeSecondBridgeErc20Args, encodeSecondBridgeEthArgs, registerErrorAbi, toZKsyncError };