@hyperbridge/simplex 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -625,6 +625,20 @@ var ConfirmationPolicy = class {
625
625
  // src/core/filler.ts
626
626
  var import_p_queue = __toESM(require("p-queue"), 1);
627
627
 
628
+ // src/config/bundlers.ts
629
+ var HYPERBRIDGE_BUNDLER_URLS = {
630
+ 1: "https://bundler.polytope.technology/ethereum",
631
+ 56: "https://bundler.polytope.technology/bsc",
632
+ 97: "https://bundler.polytope.technology/bsc-chapel",
633
+ 137: "https://bundler.polytope.technology/polygon",
634
+ 8453: "https://bundler.polytope.technology/base",
635
+ 42161: "https://bundler.polytope.technology/arbitrum",
636
+ 80002: "https://bundler.polytope.technology/polygon-amoy"
637
+ };
638
+ function hyperbridgeBundlerUrl(chainId) {
639
+ return HYPERBRIDGE_BUNDLER_URLS[chainId];
640
+ }
641
+
628
642
  // src/config/asset-registry.ts
629
643
  var import_viem = require("viem");
630
644
  var BUILTIN_ASSETS = {
@@ -1245,7 +1259,7 @@ async function resolveChainConfigs(chains, options = {}) {
1245
1259
  "RPC endpoint could not report its chainId at startup; keeping it for the quorum to judge per call"
1246
1260
  );
1247
1261
  }
1248
- return { chainId: first.chainId, rpcUrls, bundlerUrl: chain.bundlerUrl };
1262
+ return { chainId: first.chainId, rpcUrls, bundlerUrl: hyperbridgeBundlerUrl(first.chainId) };
1249
1263
  })
1250
1264
  );
1251
1265
  }
@@ -1314,12 +1328,6 @@ var FillerConfigService = class {
1314
1328
  }
1315
1329
  this.rpcOverrides.set(chainId, validateRpcUrls(rpcUrls));
1316
1330
  }
1317
- setBundlerUrl(chainId, bundlerUrl) {
1318
- if (!this.rpcOverrides.has(chainId)) {
1319
- throw new Error(`Chain ${chainId} is not configured`);
1320
- }
1321
- this.bundlerUrls.set(chainId, bundlerUrl);
1322
- }
1323
1331
  /** Replaces the rebalancing config at runtime; trigger checks read it live. */
1324
1332
  setRebalancing(rebalancing) {
1325
1333
  if (this.fillerConfig) this.fillerConfig.rebalancing = rebalancing;
@@ -1681,9 +1689,6 @@ function validateConfig(config, cliWatchOnly = false) {
1681
1689
  if (!Array.isArray(chain.rpcUrls) || chain.rpcUrls.length === 0 || chain.rpcUrls.some((u) => !u)) {
1682
1690
  throw new Error("Each chain configuration must have rpcUrls (a non-empty array of strings)");
1683
1691
  }
1684
- if (!chain.bundlerUrl) {
1685
- throw new Error("Each chain configuration must have bundlerUrl");
1686
- }
1687
1692
  }
1688
1693
  const concurrent = config.simplex.maxConcurrentOrders;
1689
1694
  if (concurrent !== void 0) {
@@ -2545,13 +2550,6 @@ var FREE_RPC_URLS = {
2545
2550
  "https://arb1.arbitrum.io/rpc"
2546
2551
  ]
2547
2552
  };
2548
- var HYPERBRIDGE_BUNDLER_URLS = {
2549
- 1: "https://bundler.polytope.technology/ethereum",
2550
- 56: "https://bundler.polytope.technology/bsc",
2551
- 137: "https://bundler.polytope.technology/polygon",
2552
- 8453: "https://bundler.polytope.technology/base",
2553
- 42161: "https://bundler.polytope.technology/arbitrum"
2554
- };
2555
2553
  var CHAIN_NATIVE_SYMBOLS = {
2556
2554
  1: "ETH",
2557
2555
  56: "BNB",
@@ -2653,7 +2651,8 @@ var INIT_CHAINS = [
2653
2651
  label: "Polygon Amoy",
2654
2652
  network: "testnet",
2655
2653
  alchemySubdomain: "polygon-amoy",
2656
- explorerUrl: external_links_default.chainExplorers.polygonAmoy
2654
+ explorerUrl: external_links_default.chainExplorers.polygonAmoy,
2655
+ hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[80002]
2657
2656
  },
2658
2657
  {
2659
2658
  chainId: 97,
@@ -2661,7 +2660,8 @@ var INIT_CHAINS = [
2661
2660
  label: "BSC Chapel",
2662
2661
  network: "testnet",
2663
2662
  alchemySubdomain: "bnb-testnet",
2664
- explorerUrl: external_links_default.chainExplorers.bnbChapel
2663
+ explorerUrl: external_links_default.chainExplorers.bnbChapel,
2664
+ hyperbridgeBundlerUrl: HYPERBRIDGE_BUNDLER_URLS[97]
2665
2665
  }
2666
2666
  ];
2667
2667
  function chainByChainId(chainId) {
@@ -4458,80 +4458,6 @@ async function patchRuntimeState(store, patch) {
4458
4458
  return next;
4459
4459
  }
4460
4460
 
4461
- // src/services/bundler-preflight.ts
4462
- var BUNDLER_PREFLIGHT_TIMEOUT_MS = 1e4;
4463
- async function assertBundlersServeEntryPoint(chains, configService, options = {}) {
4464
- const timeoutMs = options.timeoutMs ?? BUNDLER_PREFLIGHT_TIMEOUT_MS;
4465
- const logger = moduleLogger(configService.loggers, "bundler-preflight");
4466
- const failures = await Promise.all(
4467
- chains.map(async ({ chainId, bundlerUrl }) => {
4468
- if (options.watchOnly?.[chainId] === true) return void 0;
4469
- if (!bundlerUrl?.trim()) return void 0;
4470
- const entryPoint = configService.getEntryPointAddress(formatChainKey(chainId));
4471
- if (!entryPoint) return void 0;
4472
- return checkBundler(chainId, bundlerUrl.trim(), entryPoint, timeoutMs, logger);
4473
- })
4474
- );
4475
- const messages = failures.filter((failure) => failure !== void 0);
4476
- if (messages.length > 0) throw new Error(messages.join("; "));
4477
- }
4478
- function servesEntryPoint(listed, entryPoint) {
4479
- return Array.isArray(listed) && listed.some((address) => String(address).toLowerCase() === entryPoint.toLowerCase());
4480
- }
4481
- function describeEntryPoints(listed) {
4482
- return Array.isArray(listed) && listed.length > 0 ? listed.map(String).join(", ") : "none";
4483
- }
4484
- function bundlerHost(url) {
4485
- try {
4486
- return new URL(url).host || "an unparseable URL";
4487
- } catch {
4488
- return "an unparseable URL";
4489
- }
4490
- }
4491
- function chainName(chainId) {
4492
- const label = chainByChainId(chainId)?.label;
4493
- return label ? `${label} (${formatChainKey(chainId)})` : formatChainKey(chainId);
4494
- }
4495
- async function checkBundler(chainId, bundlerUrl, entryPoint, timeoutMs, logger) {
4496
- const host = bundlerHost(bundlerUrl);
4497
- const subject = `Bundler ${host} for ${chainName(chainId)}`;
4498
- const signal = AbortSignal.timeout(timeoutMs);
4499
- let listed;
4500
- try {
4501
- listed = await supportedEntryPoints(bundlerUrl, signal);
4502
- } catch (err) {
4503
- const reason = signal.aborted ? `timed out after ${timeoutMs}ms` : errorReason(err);
4504
- logger.warn(
4505
- { chain: formatChainKey(chainId), bundler: host },
4506
- `${subject} did not answer eth_supportedEntryPoints: ${reason.split(bundlerUrl).join(host)}. Continuing without confirming it serves EntryPoint ${entryPoint}`
4507
- );
4508
- return void 0;
4509
- }
4510
- if (servesEntryPoint(listed, entryPoint)) return void 0;
4511
- return `${subject} does not support EntryPoint ${entryPoint}; it lists ${describeEntryPoints(listed)}`;
4512
- }
4513
- async function supportedEntryPoints(bundlerUrl, signal) {
4514
- const response = await fetch(bundlerUrl, {
4515
- method: "POST",
4516
- headers: { "Content-Type": "application/json" },
4517
- body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_supportedEntryPoints", params: [] }),
4518
- signal
4519
- });
4520
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
4521
- const json = await response.json();
4522
- if (json.error) throw new Error(json.error.message ?? JSON.stringify(json.error));
4523
- const { result } = json;
4524
- if (!Array.isArray(result) || !result.every((address) => typeof address === "string")) {
4525
- throw new Error("the result is not a list of addresses");
4526
- }
4527
- return result;
4528
- }
4529
- function errorReason(err) {
4530
- if (!(err instanceof Error)) return String(err);
4531
- const { cause } = err;
4532
- return cause instanceof Error ? `${err.message} (${cause.message})` : err.message;
4533
- }
4534
-
4535
4461
  // src/services/wallet/mpcvault.ts
4536
4462
  var import_viem7 = require("viem");
4537
4463
  var grpc = __toESM(require("@grpc/grpc-js"), 1);
@@ -19996,7 +19922,7 @@ var UserOpSender = class {
19996
19922
  let auth;
19997
19923
  let fees;
19998
19924
  try {
19999
- fees = await this.getGasPrice(bundlerUrl, publicClient, chainId);
19925
+ fees = await this.getGasPrice(bundlerUrl, publicClient);
20000
19926
  const gasForPrefund = gas ?? {
20001
19927
  verificationGasLimit: FALLBACK_VERIFICATION_GAS_LIMIT,
20002
19928
  callGasLimit: FALLBACK_CALL_GAS_LIMIT,
@@ -20151,48 +20077,26 @@ var UserOpSender = class {
20151
20077
  return userOp;
20152
20078
  }
20153
20079
  /**
20154
- * Mirrors the gas-price selection used by the delegation and fill paths: Pimlico's and
20155
- * Alchemy's own pricing, otherwise the chain's gas price raised to the priority fee a
20156
- * rundler bundler requires, when the bundler gives one.
20080
+ * Prices the op for the rundler bundler, as the fill path does: its suggested fees, or the
20081
+ * chain's gas price raised to the priority fee it requires where it suggests none.
20157
20082
  */
20158
- async getGasPrice(bundlerUrl, publicClient, chainId) {
20159
- const lower = bundlerUrl.toLowerCase();
20160
- if (lower.includes("pimlico.io")) {
20161
- const res = await this.sendBundlerRpc(
20162
- bundlerUrl,
20163
- import_sdk8.BundlerMethod.PIMLICO_GET_USER_OPERATION_GAS_PRICE,
20164
- []
20165
- );
20166
- return { maxFeePerGas: BigInt(res.fast.maxFeePerGas), maxPriorityFeePerGas: BigInt(res.fast.maxPriorityFeePerGas) };
20167
- }
20168
- if (lower.includes("alchemy.com")) {
20169
- const [rundlerPriorityFee2, latestBlock2] = await Promise.all([
20170
- this.sendBundlerRpc(bundlerUrl, import_sdk8.BundlerMethod.RUNDLER_MAX_PRIORITY_FEE_PER_GAS, []),
20171
- publicClient.getBlock({ blockTag: "latest" })
20172
- ]);
20173
- const baseFeePerGas = latestBlock2.baseFeePerGas ?? await publicClient.getGasPrice();
20174
- const isArbitrum = BigInt(chainId) === 42161n;
20175
- const prioBump = isArbitrum ? 0n : 25n;
20176
- const maxPriorityFeePerGas = BigInt(rundlerPriorityFee2) + BigInt(rundlerPriorityFee2) * prioBump / 100n;
20177
- const bufferedBaseFee = baseFeePerGas + baseFeePerGas * 50n / 100n;
20178
- return { maxFeePerGas: bufferedBaseFee + maxPriorityFeePerGas, maxPriorityFeePerGas };
20179
- }
20180
- const [gasPrice, rundlerPriorityFee] = await Promise.all([
20083
+ async getGasPrice(bundlerUrl, publicClient) {
20084
+ const [gasPrice, latestBlock] = await Promise.all([
20181
20085
  publicClient.getGasPrice(),
20182
- (0, import_sdk8.fetchRundlerPriorityFee)(bundlerUrl)
20086
+ publicClient.getBlock({ blockTag: "latest" })
20183
20087
  ]);
20184
- const fees = {
20185
- maxFeePerGas: gasPrice + gasPrice * MAX_FEE_BUMP_PERCENT / 100n,
20186
- maxPriorityFeePerGas: gasPrice + gasPrice * PRIORITY_FEE_BUMP_PERCENT / 100n
20187
- };
20188
- if (rundlerPriorityFee === null) return fees;
20189
- const latestBlock = await publicClient.getBlock({ blockTag: "latest" });
20190
- return (0, import_sdk8.applyRundlerPriorityFee)(fees, {
20191
- rundlerPriorityFee,
20192
- baseFeePerGas: latestBlock.baseFeePerGas ?? gasPrice,
20193
- priorityFeeBumpPercent: PRIORITY_FEE_BUMP_PERCENT,
20194
- maxFeeBumpPercent: MAX_FEE_BUMP_PERCENT
20195
- });
20088
+ return (0, import_sdk8.rundlerUserOperationFees)(
20089
+ bundlerUrl,
20090
+ {
20091
+ maxFeePerGas: gasPrice + gasPrice * MAX_FEE_BUMP_PERCENT / 100n,
20092
+ maxPriorityFeePerGas: gasPrice + gasPrice * PRIORITY_FEE_BUMP_PERCENT / 100n
20093
+ },
20094
+ {
20095
+ baseFeePerGas: latestBlock.baseFeePerGas ?? gasPrice,
20096
+ priorityFeeBumpPercent: PRIORITY_FEE_BUMP_PERCENT,
20097
+ maxFeeBumpPercent: MAX_FEE_BUMP_PERCENT
20098
+ }
20099
+ );
20196
20100
  }
20197
20101
  async sendBundlerRpc(bundlerUrl, method, params) {
20198
20102
  const response = await fetch(bundlerUrl, {
@@ -21004,7 +20908,7 @@ var BinanceRebalancer = class {
21004
20908
  // src/services/rebalancers/cctp.ts
21005
20909
  var import_bridge_kit = require("@circle-fin/bridge-kit");
21006
20910
  var import_adapter_viem_v2 = require("@circle-fin/adapter-viem-v2");
21007
- var import_chains2 = require("@circle-fin/bridge-kit/chains");
20911
+ var import_chains = require("@circle-fin/bridge-kit/chains");
21008
20912
  var import_sdk11 = require("@hyperbridge/sdk");
21009
20913
  var CHAIN_ID_TO_CCTP = {
21010
20914
  1: "Ethereum",
@@ -21057,18 +20961,18 @@ var CctpRebalancer = class {
21057
20961
  {
21058
20962
  addressContext: "user-controlled",
21059
20963
  supportedChains: [
21060
- import_chains2.Ethereum,
21061
- import_chains2.EthereumSepolia,
21062
- import_chains2.Arbitrum,
21063
- import_chains2.ArbitrumSepolia,
21064
- import_chains2.Base,
21065
- import_chains2.BaseSepolia,
21066
- import_chains2.Optimism,
21067
- import_chains2.OptimismSepolia,
21068
- import_chains2.Polygon,
21069
- import_chains2.PolygonAmoy,
21070
- import_chains2.Unichain,
21071
- import_chains2.UnichainSepolia
20964
+ import_chains.Ethereum,
20965
+ import_chains.EthereumSepolia,
20966
+ import_chains.Arbitrum,
20967
+ import_chains.ArbitrumSepolia,
20968
+ import_chains.Base,
20969
+ import_chains.BaseSepolia,
20970
+ import_chains.Optimism,
20971
+ import_chains.OptimismSepolia,
20972
+ import_chains.Polygon,
20973
+ import_chains.PolygonAmoy,
20974
+ import_chains.Unichain,
20975
+ import_chains.UnichainSepolia
21072
20976
  ]
21073
20977
  }
21074
20978
  );
@@ -23913,6 +23817,82 @@ var TokenSender = class {
23913
23817
  }
23914
23818
  };
23915
23819
 
23820
+ // src/services/bundler-preflight.ts
23821
+ var BUNDLER_PREFLIGHT_TIMEOUT_MS = 1e4;
23822
+ async function assertBundlersServeEntryPoint(chains, configService, options = {}) {
23823
+ const timeoutMs = options.timeoutMs ?? BUNDLER_PREFLIGHT_TIMEOUT_MS;
23824
+ const logger = moduleLogger(configService.loggers, "bundler-preflight");
23825
+ const failures = await Promise.all(
23826
+ chains.map(async ({ chainId, bundlerUrl }) => {
23827
+ if (options.watchOnly?.[chainId] === true) return void 0;
23828
+ if (!bundlerUrl?.trim()) {
23829
+ return `Hyperbridge runs no bundler for ${chainName(chainId)}, so simplex cannot fill there; set it watch-only`;
23830
+ }
23831
+ const entryPoint = configService.getEntryPointAddress(formatChainKey(chainId));
23832
+ if (!entryPoint) return void 0;
23833
+ return checkBundler(chainId, bundlerUrl.trim(), entryPoint, timeoutMs, logger);
23834
+ })
23835
+ );
23836
+ const messages = failures.filter((failure) => failure !== void 0);
23837
+ if (messages.length > 0) throw new Error(messages.join("; "));
23838
+ }
23839
+ function servesEntryPoint(listed, entryPoint) {
23840
+ return Array.isArray(listed) && listed.some((address) => String(address).toLowerCase() === entryPoint.toLowerCase());
23841
+ }
23842
+ function describeEntryPoints(listed) {
23843
+ return Array.isArray(listed) && listed.length > 0 ? listed.map(String).join(", ") : "none";
23844
+ }
23845
+ function bundlerHost(url) {
23846
+ try {
23847
+ return new URL(url).host || "an unparseable URL";
23848
+ } catch {
23849
+ return "an unparseable URL";
23850
+ }
23851
+ }
23852
+ function chainName(chainId) {
23853
+ const label = chainByChainId(chainId)?.label;
23854
+ return label ? `${label} (${formatChainKey(chainId)})` : formatChainKey(chainId);
23855
+ }
23856
+ async function checkBundler(chainId, bundlerUrl, entryPoint, timeoutMs, logger) {
23857
+ const host = bundlerHost(bundlerUrl);
23858
+ const subject = `Bundler ${host} for ${chainName(chainId)}`;
23859
+ const signal = AbortSignal.timeout(timeoutMs);
23860
+ let listed;
23861
+ try {
23862
+ listed = await supportedEntryPoints(bundlerUrl, signal);
23863
+ } catch (err) {
23864
+ const reason = signal.aborted ? `timed out after ${timeoutMs}ms` : errorReason(err);
23865
+ logger.warn(
23866
+ { chain: formatChainKey(chainId), bundler: host },
23867
+ `${subject} did not answer eth_supportedEntryPoints: ${reason.split(bundlerUrl).join(host)}. Continuing without confirming it serves EntryPoint ${entryPoint}`
23868
+ );
23869
+ return void 0;
23870
+ }
23871
+ if (servesEntryPoint(listed, entryPoint)) return void 0;
23872
+ return `${subject} does not support EntryPoint ${entryPoint}; it lists ${describeEntryPoints(listed)}`;
23873
+ }
23874
+ async function supportedEntryPoints(bundlerUrl, signal) {
23875
+ const response = await fetch(bundlerUrl, {
23876
+ method: "POST",
23877
+ headers: { "Content-Type": "application/json" },
23878
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_supportedEntryPoints", params: [] }),
23879
+ signal
23880
+ });
23881
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
23882
+ const json = await response.json();
23883
+ if (json.error) throw new Error(json.error.message ?? JSON.stringify(json.error));
23884
+ const { result } = json;
23885
+ if (!Array.isArray(result) || !result.every((address) => typeof address === "string")) {
23886
+ throw new Error("the result is not a list of addresses");
23887
+ }
23888
+ return result;
23889
+ }
23890
+ function errorReason(err) {
23891
+ if (!(err instanceof Error)) return String(err);
23892
+ const { cause } = err;
23893
+ return cause instanceof Error ? `${err.message} (${cause.message})` : err.message;
23894
+ }
23895
+
23916
23896
  // src/orderbook/lifecycle.ts
23917
23897
  var EXPIRY_SWEEP_MS = 3e4;
23918
23898
  var LimitOrderLifecycle = class {
@@ -25989,7 +25969,7 @@ var OrderScanner = class _OrderScanner {
25989
25969
  async addChainNow(chain) {
25990
25970
  if (this.closed) throw new Error("This OrderScanner is closed");
25991
25971
  const rpcUrls = validateRpcUrls(chain.rpcUrls);
25992
- const chainId = chain.chainId ?? (await resolveChainConfigs([{ rpcUrls, bundlerUrl: chain.bundlerUrl ?? "" }], {
25972
+ const chainId = chain.chainId ?? (await resolveChainConfigs([{ rpcUrls }], {
25993
25973
  loggers: this.loggers,
25994
25974
  tolerateUnreachable: true
25995
25975
  }))[0].chainId;
@@ -26421,10 +26401,7 @@ var ChainController = class {
26421
26401
  async add(chain) {
26422
26402
  return this.serialise(async () => {
26423
26403
  validateRpcUrls(chain.rpcUrls);
26424
- if (!chain.bundlerUrl?.trim()) {
26425
- throw new Error("A bundler URL is required to submit fill UserOperations");
26426
- }
26427
- const [resolved] = await resolveChainConfigs([{ rpcUrls: chain.rpcUrls, bundlerUrl: chain.bundlerUrl }]);
26404
+ const [resolved] = await resolveChainConfigs([{ rpcUrls: chain.rpcUrls }]);
26428
26405
  const { chainId } = resolved;
26429
26406
  const { configService, config, intentFiller } = this.runtime;
26430
26407
  if (configService.getConfiguredChainIds().includes(chainId)) {
@@ -26453,7 +26430,7 @@ var ChainController = class {
26453
26430
  if (watchOnly) intentFiller.setWatchOnly(chainId, true);
26454
26431
  try {
26455
26432
  if (!inScanner) {
26456
- await this.scanner.addChain({ rpcUrls: chain.rpcUrls, bundlerUrl: chain.bundlerUrl, chainId });
26433
+ await this.scanner.addChain({ rpcUrls: chain.rpcUrls, chainId });
26457
26434
  }
26458
26435
  this.runtime.chainClientManager.invalidate(formatChainKey(chainId));
26459
26436
  await intentFiller.addChain(configService.getChainConfig(formatChainKey(chainId)));
@@ -26470,7 +26447,7 @@ var ChainController = class {
26470
26447
  this.runtime.confirmationPolicy.adopt(chainId, resolvedPolicy);
26471
26448
  }
26472
26449
  this.runtime.resolvedChains.push(resolved);
26473
- config.chains = [...config.chains, { rpcUrls: chain.rpcUrls, bundlerUrl: chain.bundlerUrl }];
26450
+ config.chains = [...config.chains, { rpcUrls: chain.rpcUrls }];
26474
26451
  if (Object.keys(confirmationPolicies).length > 0) config.confirmationPolicies = confirmationPolicies;
26475
26452
  this.syncWatchOnlyToConfig();
26476
26453
  await this.persist();
@@ -26515,9 +26492,7 @@ var ChainController = class {
26515
26492
  validateRpcUrls(rpcUrls);
26516
26493
  const index = this.runtime.resolvedChains.findIndex((chain) => chain.chainId === chainId);
26517
26494
  if (index < 0) throw new Error(`Chain ${chainId} is not configured`);
26518
- const [probed] = await resolveChainConfigs([
26519
- { rpcUrls, bundlerUrl: this.runtime.resolvedChains[index].bundlerUrl ?? "" }
26520
- ]);
26495
+ const [probed] = await resolveChainConfigs([{ rpcUrls }]);
26521
26496
  if (probed.chainId !== chainId) {
26522
26497
  throw new Error(`Those endpoints answer for chain ${probed.chainId}, not ${chainId}`);
26523
26498
  }
@@ -26536,20 +26511,6 @@ var ChainController = class {
26536
26511
  await this.persist();
26537
26512
  });
26538
26513
  }
26539
- async setBundlerUrl(chainId, bundlerUrl) {
26540
- return this.serialise(async () => {
26541
- if (!bundlerUrl?.trim()) throw new Error("A bundler URL is required");
26542
- const index = this.runtime.resolvedChains.findIndex((chain) => chain.chainId === chainId);
26543
- if (index < 0) throw new Error(`Chain ${chainId} is not configured`);
26544
- await assertBundlersServeEntryPoint([{ chainId, bundlerUrl }], this.runtime.configService, {
26545
- watchOnly: this.runtime.intentFiller.getWatchOnly()
26546
- });
26547
- this.runtime.configService.setBundlerUrl(chainId, bundlerUrl);
26548
- this.runtime.resolvedChains[index].bundlerUrl = bundlerUrl;
26549
- this.runtime.config.chains[index].bundlerUrl = bundlerUrl;
26550
- await this.persist();
26551
- });
26552
- }
26553
26514
  /** Monitor without filling. Takes effect on the next order. */
26554
26515
  async setWatchOnly(chainId, watchOnly) {
26555
26516
  return this.serialise(async () => {