@hyperbridge/sdk 1.8.8 → 1.9.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.
@@ -606,7 +606,6 @@ var IntentOrderStatus = Object.freeze({
606
606
  AWAITING_BIDS: "AWAITING_BIDS",
607
607
  BIDS_RECEIVED: "BIDS_RECEIVED",
608
608
  BID_SELECTED: "BID_SELECTED",
609
- USEROP_SUBMITTED: "USEROP_SUBMITTED",
610
609
  FILLED: "FILLED",
611
610
  PARTIAL_FILL: "PARTIAL_FILL",
612
611
  EXPIRED: "EXPIRED",
@@ -5583,6 +5582,7 @@ var EvmChain = class _EvmChain {
5583
5582
  });
5584
5583
  this.chainConfigService = new ChainConfigService();
5585
5584
  }
5585
+ params;
5586
5586
  publicClient;
5587
5587
  chainConfigService;
5588
5588
  /**
@@ -6183,6 +6183,7 @@ var HttpRpcClient = class {
6183
6183
  constructor(url) {
6184
6184
  this.url = url;
6185
6185
  }
6186
+ url;
6186
6187
  /**
6187
6188
  * Make an RPC call over HTTP
6188
6189
  * @param method - The RPC method name
@@ -6220,6 +6221,7 @@ var SubstrateChain = class _SubstrateChain {
6220
6221
  const httpUrl = replaceWebsocketWithHttp(url);
6221
6222
  this.rpcClient = new HttpRpcClient(httpUrl);
6222
6223
  }
6224
+ params;
6223
6225
  /*
6224
6226
  * api: The Polkadot API instance for the Substrate chain.
6225
6227
  */
@@ -6737,6 +6739,9 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
6737
6739
  this.substratePrivateKey = substratePrivateKey;
6738
6740
  this.ownsConnection = ownsConnection;
6739
6741
  }
6742
+ api;
6743
+ substratePrivateKey;
6744
+ ownsConnection;
6740
6745
  /** Cached result of whether the node exposes intents_* RPC methods */
6741
6746
  hasIntentsRpc = null;
6742
6747
  /**
@@ -7014,6 +7019,7 @@ var TronChain = class _TronChain {
7014
7019
  this.evm = evm;
7015
7020
  this.tronWebInstance = new TronWeb({ fullHost: params.rpcUrl });
7016
7021
  }
7022
+ params;
7017
7023
  evm;
7018
7024
  tronWebInstance;
7019
7025
  /**
@@ -7554,6 +7560,7 @@ var SubstrateHttpRpc = class {
7554
7560
  constructor(url) {
7555
7561
  this.url = url;
7556
7562
  }
7563
+ url;
7557
7564
  async call(method, params = []) {
7558
7565
  const body = JSON.stringify({
7559
7566
  jsonrpc: "2.0",
@@ -7598,6 +7605,7 @@ var PolkadotHubChain = class _PolkadotHubChain {
7598
7605
  this.evm = evm;
7599
7606
  this.substrateRpc = new SubstrateHttpRpc(replaceWebsocketWithHttp(params.substrateRpcUrl));
7600
7607
  }
7608
+ params;
7601
7609
  evm;
7602
7610
  substrateRpc;
7603
7611
  static fromParams(params) {
@@ -12689,6 +12697,7 @@ var CryptoUtils = class {
12689
12697
  constructor(ctx) {
12690
12698
  this.ctx = ctx;
12691
12699
  }
12700
+ ctx;
12692
12701
  /**
12693
12702
  * Computes an EIP-712 domain separator for a given contract.
12694
12703
  *
@@ -15224,6 +15233,7 @@ var OrderPlacer = class {
15224
15233
  constructor(ctx) {
15225
15234
  this.ctx = ctx;
15226
15235
  }
15236
+ ctx;
15227
15237
  /**
15228
15238
  * Bidirectional async generator that orchestrates order placement.
15229
15239
  *
@@ -15301,67 +15311,40 @@ var OrderPlacer = class {
15301
15311
  return { order, receipt };
15302
15312
  }
15303
15313
  };
15304
-
15305
- // src/protocols/intents/OrderExecutor.ts
15306
15314
  var USED_USEROPS_STORAGE_KEY = (commitment) => `used-userops:${commitment.toLowerCase()}`;
15307
15315
  var OrderExecutor = class {
15308
- /**
15309
- * @param ctx - Shared IntentsV2 context providing the destination chain
15310
- * client, coprocessor, bundler URL, and storage adapters.
15311
- * @param bidManager - Handles bid validation, sorting, simulation, and
15312
- * UserOperation submission.
15313
- * @param crypto - Crypto utilities used to compute UserOperation hashes for
15314
- * deduplication.
15315
- */
15316
15316
  constructor(ctx, bidManager, crypto) {
15317
15317
  this.ctx = ctx;
15318
15318
  this.bidManager = bidManager;
15319
15319
  this.crypto = crypto;
15320
15320
  }
15321
+ ctx;
15322
+ bidManager;
15323
+ crypto;
15321
15324
  /**
15322
- * Async generator that executes an intent order by polling for bids and
15323
- * submitting UserOperations until the order is filled, partially exhausted,
15324
- * or an unrecoverable error occurs.
15325
- *
15326
- * **Status progression (cross-chain orders):**
15327
- * `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED` → `USEROP_SUBMITTED`
15328
- * then terminates (settlement is confirmed off-chain via Hyperbridge).
15329
- *
15330
- * **Status progression (same-chain orders):**
15331
- * `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED` → `USEROP_SUBMITTED`
15332
- * → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
15333
- *
15334
- * **Error statuses:** `FAILED` (retryable error during bid selection/submission,
15335
- * triggers automatic retry) or `EXPIRED` (deadline reached or no new bids —
15336
- * terminal, no further retries).
15337
- *
15338
- * @param options - Execution parameters including the placed order, its
15339
- * session private key, bid collection settings, and poll interval.
15340
- * @yields {@link IntentOrderStatusUpdate} objects describing each stage.
15341
- * @throws Never throws directly; all errors are reported as `FAILED` yields.
15325
+ * Sleeps until the order's block deadline is reached, then yields EXPIRED.
15326
+ * Uses the chain's block time to calculate the sleep duration.
15342
15327
  */
15343
- async *executeIntentOrder(options) {
15344
- const {
15345
- order,
15346
- sessionPrivateKey,
15347
- minBids = 1,
15348
- bidTimeoutMs = 6e4,
15349
- pollIntervalMs = DEFAULT_POLL_INTERVAL,
15350
- solver
15351
- } = options;
15352
- const commitment = order.id;
15353
- const isSameChain = order.source === order.destination;
15354
- if (!this.ctx.intentsCoprocessor) {
15355
- yield { status: "FAILED", error: "IntentsCoprocessor required for order execution" };
15356
- return;
15357
- }
15358
- if (!this.ctx.bundlerUrl) {
15359
- yield { status: "FAILED", error: "Bundler URL not configured" };
15360
- return;
15328
+ async *deadlineStream(deadline, commitment) {
15329
+ const client = this.ctx.dest.client;
15330
+ const blockTimeMs = client.chain?.blockTime ?? 2e3;
15331
+ while (true) {
15332
+ const currentBlock = await client.getBlockNumber();
15333
+ if (currentBlock >= deadline) break;
15334
+ const blocksRemaining = Number(deadline - currentBlock);
15335
+ const sleepMs = blocksRemaining * blockTimeMs;
15336
+ await sleep(sleepMs);
15361
15337
  }
15338
+ yield {
15339
+ status: "EXPIRED",
15340
+ commitment,
15341
+ error: "Order deadline reached"
15342
+ };
15343
+ }
15344
+ /** Loads the persisted deduplication set of already-submitted UserOp hashes for a given order commitment. */
15345
+ async loadUsedUserOps(commitment) {
15362
15346
  const usedUserOps = /* @__PURE__ */ new Set();
15363
- const storageKey = USED_USEROPS_STORAGE_KEY(commitment);
15364
- const persisted = await this.ctx.usedUserOpsStorage.getItem(storageKey);
15347
+ const persisted = await this.ctx.usedUserOpsStorage.getItem(USED_USEROPS_STORAGE_KEY(commitment));
15365
15348
  if (persisted) {
15366
15349
  try {
15367
15350
  const parsed = JSON.parse(persisted);
@@ -15371,74 +15354,214 @@ var OrderExecutor = class {
15371
15354
  } catch {
15372
15355
  }
15373
15356
  }
15374
- const persistUsedUserOps = async () => {
15375
- await this.ctx.usedUserOpsStorage.setItem(storageKey, JSON.stringify([...usedUserOps]));
15376
- };
15357
+ return usedUserOps;
15358
+ }
15359
+ /** Persists the deduplication set of UserOp hashes to storage. */
15360
+ async persistUsedUserOps(commitment, usedUserOps) {
15361
+ await this.ctx.usedUserOpsStorage.setItem(
15362
+ USED_USEROPS_STORAGE_KEY(commitment),
15363
+ JSON.stringify([...usedUserOps])
15364
+ );
15365
+ }
15366
+ /**
15367
+ * Creates a closure that computes the deduplication hash key for a
15368
+ * UserOperation, pre-bound to the order's destination chain and entry point.
15369
+ */
15370
+ createUserOpHasher(order) {
15377
15371
  const entryPointAddress = this.ctx.dest.configService.getEntryPointV08Address(hexToString(order.destination));
15378
15372
  const chainId = BigInt(
15379
15373
  this.ctx.dest.client.chain?.id ?? Number.parseInt(this.ctx.dest.config.stateMachineId.split("-")[1])
15380
15374
  );
15381
- const userOpHashKey = (userOp) => this.crypto.computeUserOpHash(userOp, entryPointAddress, chainId);
15375
+ return (userOp) => this.crypto.computeUserOpHash(userOp, entryPointAddress, chainId);
15376
+ }
15377
+ /**
15378
+ * Fetches bids from the coprocessor for a given order commitment.
15379
+ * If a preferred solver is configured and the solver lock has not expired,
15380
+ * only bids from that solver are returned.
15381
+ */
15382
+ async fetchBids(params) {
15383
+ const { commitment, solver, solverLockStartTime } = params;
15384
+ const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
15385
+ if (solver) {
15386
+ const { address, timeoutMs } = solver;
15387
+ const solverLockActive = Date.now() - solverLockStartTime < timeoutMs;
15388
+ return solverLockActive ? fetchedBids.filter((bid) => bid.userOp.sender.toLowerCase() === address.toLowerCase()) : fetchedBids;
15389
+ }
15390
+ return fetchedBids;
15391
+ }
15392
+ /**
15393
+ * Selects the best bid from the provided candidates, submits the
15394
+ * UserOperation, and persists the dedup entry to prevent resubmission.
15395
+ */
15396
+ async submitBid(params) {
15397
+ const { order, freshBids, sessionPrivateKey, commitment, usedUserOps, userOpHashKey } = params;
15398
+ const result = await this.bidManager.selectBid(order, freshBids, sessionPrivateKey);
15399
+ usedUserOps.add(userOpHashKey(result.userOp));
15400
+ await this.persistUsedUserOps(commitment, usedUserOps);
15401
+ return result;
15402
+ }
15403
+ /**
15404
+ * Processes a fill result and returns updated fill accumulators,
15405
+ * the status update to yield (if any), and whether the order is
15406
+ * fully satisfied.
15407
+ */
15408
+ processFillResult(result, commitment, targetAssets, totalFilledAssets, remainingAssets) {
15409
+ if (result.fillStatus === "full") {
15410
+ totalFilledAssets = targetAssets.map((a) => ({ token: a.token, amount: a.amount }));
15411
+ remainingAssets = targetAssets.map((a) => ({ token: a.token, amount: 0n }));
15412
+ return {
15413
+ update: {
15414
+ status: "FILLED",
15415
+ commitment,
15416
+ userOpHash: result.userOpHash,
15417
+ selectedSolver: result.solverAddress,
15418
+ transactionHash: result.txnHash,
15419
+ totalFilledAssets,
15420
+ remainingAssets
15421
+ },
15422
+ done: true,
15423
+ totalFilledAssets,
15424
+ remainingAssets
15425
+ };
15426
+ }
15427
+ if (result.fillStatus === "partial") {
15428
+ const filledAssets = result.filledAssets ?? [];
15429
+ totalFilledAssets = totalFilledAssets.map((a) => {
15430
+ const filled = filledAssets.find((f) => f.token === a.token);
15431
+ return filled ? { token: a.token, amount: a.amount + filled.amount } : { ...a };
15432
+ });
15433
+ remainingAssets = targetAssets.map((target) => {
15434
+ const filled = totalFilledAssets.find((a) => a.token === target.token);
15435
+ const filledAmt = filled?.amount ?? 0n;
15436
+ return {
15437
+ token: target.token,
15438
+ amount: filledAmt >= target.amount ? 0n : target.amount - filledAmt
15439
+ };
15440
+ });
15441
+ const fullyFilled = remainingAssets.every((a) => a.amount === 0n);
15442
+ return {
15443
+ update: fullyFilled ? {
15444
+ status: "FILLED",
15445
+ commitment,
15446
+ userOpHash: result.userOpHash,
15447
+ selectedSolver: result.solverAddress,
15448
+ transactionHash: result.txnHash,
15449
+ totalFilledAssets,
15450
+ remainingAssets
15451
+ } : {
15452
+ status: "PARTIAL_FILL",
15453
+ commitment,
15454
+ userOpHash: result.userOpHash,
15455
+ selectedSolver: result.solverAddress,
15456
+ transactionHash: result.txnHash,
15457
+ filledAssets,
15458
+ totalFilledAssets,
15459
+ remainingAssets
15460
+ },
15461
+ done: fullyFilled,
15462
+ totalFilledAssets,
15463
+ remainingAssets
15464
+ };
15465
+ }
15466
+ return { update: null, done: false, totalFilledAssets, remainingAssets };
15467
+ }
15468
+ /**
15469
+ * Executes an intent order by racing bid polling against the order's
15470
+ * block deadline. Yields status updates at each lifecycle stage.
15471
+ *
15472
+ * **Same-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
15473
+ * → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
15474
+ *
15475
+ * **Cross-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
15476
+ * (terminates — settlement is confirmed async via Hyperbridge)
15477
+ */
15478
+ async *executeOrder(options) {
15479
+ const { order, sessionPrivateKey, auctionTimeMs, pollIntervalMs = DEFAULT_POLL_INTERVAL, solver } = options;
15480
+ const commitment = order.id;
15481
+ const isSameChain = order.source === order.destination;
15482
+ if (!this.ctx.intentsCoprocessor) {
15483
+ yield { status: "FAILED", error: "IntentsCoprocessor required for order execution" };
15484
+ return;
15485
+ }
15486
+ if (!this.ctx.bundlerUrl) {
15487
+ yield { status: "FAILED", error: "Bundler URL not configured" };
15488
+ return;
15489
+ }
15490
+ const usedUserOps = await this.loadUsedUserOps(commitment);
15491
+ const userOpHashKey = this.createUserOpHasher(order);
15382
15492
  const targetAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
15383
15493
  let totalFilledAssets = order.output.assets.map((a) => ({ token: a.token, amount: 0n }));
15384
15494
  let remainingAssets = order.output.assets.map((a) => ({ token: a.token, amount: a.amount }));
15495
+ const executionStream = this.executionStream({
15496
+ order,
15497
+ sessionPrivateKey,
15498
+ commitment,
15499
+ auctionTimeMs,
15500
+ pollIntervalMs,
15501
+ solver,
15502
+ usedUserOps,
15503
+ userOpHashKey,
15504
+ targetAssets,
15505
+ totalFilledAssets,
15506
+ remainingAssets
15507
+ });
15508
+ const deadlineTimeout = this.deadlineStream(order.deadline, commitment);
15509
+ const combined = mergeRace(deadlineTimeout, executionStream);
15510
+ for await (const update of combined) {
15511
+ yield update;
15512
+ if (update.status === "EXPIRED" || update.status === "FILLED") return;
15513
+ if (update.status === "BID_SELECTED" && !isSameChain) return;
15514
+ }
15515
+ }
15516
+ /**
15517
+ * Core execution loop that polls for bids, submits UserOperations,
15518
+ * and tracks fill progress. Yields between each poll iteration so
15519
+ * that `mergeRace` can interleave the deadline stream.
15520
+ */
15521
+ async *executionStream(params) {
15522
+ const {
15523
+ order,
15524
+ sessionPrivateKey,
15525
+ commitment,
15526
+ auctionTimeMs,
15527
+ pollIntervalMs,
15528
+ solver,
15529
+ usedUserOps,
15530
+ userOpHashKey,
15531
+ targetAssets
15532
+ } = params;
15533
+ let { totalFilledAssets, remainingAssets } = params;
15534
+ const solverLockStartTime = Date.now();
15535
+ yield { status: "AWAITING_BIDS", commitment, totalFilledAssets, remainingAssets };
15385
15536
  try {
15537
+ const auctionEnd = Date.now() + auctionTimeMs;
15538
+ while (Date.now() < auctionEnd) {
15539
+ await sleep(Math.min(pollIntervalMs, auctionEnd - Date.now()));
15540
+ }
15386
15541
  while (true) {
15387
- const currentBlock = await this.ctx.dest.client.getBlockNumber();
15388
- if (currentBlock >= order.deadline) {
15389
- const deadlineError = `Order deadline reached (block ${currentBlock} >= ${order.deadline})`;
15390
- yield {
15391
- status: "EXPIRED",
15392
- commitment,
15393
- totalFilledAssets,
15394
- remainingAssets,
15395
- error: deadlineError
15396
- };
15397
- return;
15398
- }
15399
- yield { status: "AWAITING_BIDS", commitment, totalFilledAssets, remainingAssets };
15400
- const startTime = Date.now();
15401
- let bids = [];
15402
- let solverLockExpired = false;
15403
- while (Date.now() - startTime < bidTimeoutMs) {
15404
- try {
15405
- const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
15406
- if (solver) {
15407
- const { address, timeoutMs } = solver;
15408
- const solverLockActive = Date.now() - startTime < timeoutMs;
15409
- if (!solverLockActive) solverLockExpired = true;
15410
- bids = solverLockActive ? fetchedBids.filter((bid) => bid.userOp.sender.toLowerCase() === address.toLowerCase()) : fetchedBids;
15411
- } else {
15412
- bids = fetchedBids;
15413
- }
15414
- if (bids.length >= minBids) {
15415
- break;
15416
- }
15417
- } catch {
15418
- }
15542
+ let freshBids;
15543
+ try {
15544
+ const bids = await this.fetchBids({ commitment, solver, solverLockStartTime });
15545
+ freshBids = bids.filter((bid) => !usedUserOps.has(userOpHashKey(bid.userOp)));
15546
+ } catch {
15419
15547
  await sleep(pollIntervalMs);
15548
+ continue;
15420
15549
  }
15421
- const freshBids = bids.filter((bid) => {
15422
- const key = userOpHashKey(bid.userOp);
15423
- return !usedUserOps.has(key);
15424
- });
15425
15550
  if (freshBids.length === 0) {
15426
- const solverClause = solver && !solverLockExpired ? ` for requested solver ${solver.address}` : "";
15427
- const isPartiallyFilled = totalFilledAssets.some((a) => a.amount > 0n);
15428
- const noBidsError = isPartiallyFilled ? `No new bids${solverClause} after partial fill` : `No new bids${solverClause} available within ${bidTimeoutMs}ms timeout`;
15429
- yield {
15430
- status: "EXPIRED",
15431
- commitment,
15432
- totalFilledAssets,
15433
- remainingAssets,
15434
- error: noBidsError
15435
- };
15436
- return;
15551
+ await sleep(pollIntervalMs);
15552
+ continue;
15437
15553
  }
15438
15554
  yield { status: "BIDS_RECEIVED", commitment, bidCount: freshBids.length, bids: freshBids };
15439
- let result;
15555
+ let submitResult;
15440
15556
  try {
15441
- result = await this.bidManager.selectBid(order, freshBids, sessionPrivateKey);
15557
+ submitResult = await this.submitBid({
15558
+ order,
15559
+ freshBids,
15560
+ sessionPrivateKey,
15561
+ commitment,
15562
+ usedUserOps,
15563
+ userOpHashKey
15564
+ });
15442
15565
  } catch (err) {
15443
15566
  yield {
15444
15567
  status: "FAILED",
@@ -15450,77 +15573,26 @@ var OrderExecutor = class {
15450
15573
  await sleep(pollIntervalMs);
15451
15574
  continue;
15452
15575
  }
15453
- const usedKey = userOpHashKey(result.userOp);
15454
- usedUserOps.add(usedKey);
15455
- await persistUsedUserOps();
15456
15576
  yield {
15457
15577
  status: "BID_SELECTED",
15458
15578
  commitment,
15459
- selectedSolver: result.solverAddress,
15460
- userOpHash: result.userOpHash,
15461
- userOp: result.userOp
15579
+ selectedSolver: submitResult.solverAddress,
15580
+ userOpHash: submitResult.userOpHash,
15581
+ userOp: submitResult.userOp,
15582
+ transactionHash: submitResult.txnHash
15462
15583
  };
15463
- yield {
15464
- status: "USEROP_SUBMITTED",
15584
+ const fill = this.processFillResult(
15585
+ submitResult,
15465
15586
  commitment,
15466
- userOpHash: result.userOpHash,
15467
- selectedSolver: result.solverAddress,
15468
- transactionHash: result.txnHash
15469
- };
15470
- if (!isSameChain) {
15471
- return;
15472
- }
15473
- if (result.fillStatus === "full") {
15474
- totalFilledAssets = targetAssets.map((a) => ({ token: a.token, amount: a.amount }));
15475
- remainingAssets = targetAssets.map((a) => ({ token: a.token, amount: 0n }));
15476
- yield {
15477
- status: "FILLED",
15478
- commitment,
15479
- userOpHash: result.userOpHash,
15480
- selectedSolver: result.solverAddress,
15481
- transactionHash: result.txnHash,
15482
- totalFilledAssets,
15483
- remainingAssets
15484
- };
15485
- return;
15486
- }
15487
- if (result.fillStatus === "partial") {
15488
- const filledAssets = result.filledAssets ?? [];
15489
- for (const filled of filledAssets) {
15490
- const entry = totalFilledAssets.find((a) => a.token === filled.token);
15491
- if (entry) entry.amount += filled.amount;
15492
- }
15493
- remainingAssets = targetAssets.map((target) => {
15494
- const filled = totalFilledAssets.find((a) => a.token === target.token);
15495
- const filledAmt = filled?.amount ?? 0n;
15496
- return {
15497
- token: target.token,
15498
- amount: filledAmt >= target.amount ? 0n : target.amount - filledAmt
15499
- };
15500
- });
15501
- const fullyFilled = remainingAssets.every((a) => a.amount === 0n);
15502
- if (fullyFilled) {
15503
- yield {
15504
- status: "FILLED",
15505
- commitment,
15506
- userOpHash: result.userOpHash,
15507
- selectedSolver: result.solverAddress,
15508
- transactionHash: result.txnHash,
15509
- totalFilledAssets,
15510
- remainingAssets
15511
- };
15512
- return;
15513
- }
15514
- yield {
15515
- status: "PARTIAL_FILL",
15516
- commitment,
15517
- userOpHash: result.userOpHash,
15518
- selectedSolver: result.solverAddress,
15519
- transactionHash: result.txnHash,
15520
- filledAssets,
15521
- totalFilledAssets,
15522
- remainingAssets
15523
- };
15587
+ targetAssets,
15588
+ totalFilledAssets,
15589
+ remainingAssets
15590
+ );
15591
+ totalFilledAssets = fill.totalFilledAssets;
15592
+ remainingAssets = fill.remainingAssets;
15593
+ if (fill.update) {
15594
+ yield fill.update;
15595
+ if (fill.done) return;
15524
15596
  }
15525
15597
  }
15526
15598
  } catch (err) {
@@ -15540,6 +15612,7 @@ var OrderCanceller = class {
15540
15612
  constructor(ctx) {
15541
15613
  this.ctx = ctx;
15542
15614
  }
15615
+ ctx;
15543
15616
  /**
15544
15617
  * Returns both the native token cost and the relayer fee for cancelling an
15545
15618
  * order. Frontends can use `relayerFee` to approve the ERC-20 spend before
@@ -16009,6 +16082,8 @@ var BidManager = class {
16009
16082
  this.ctx = ctx;
16010
16083
  this.crypto = crypto;
16011
16084
  }
16085
+ ctx;
16086
+ crypto;
16012
16087
  /**
16013
16088
  * Constructs a signed `PackedUserOperation` that a solver can submit to the
16014
16089
  * Hyperbridge coprocessor as a bid to fill an order.
@@ -18088,6 +18163,8 @@ var GasEstimator = class {
18088
18163
  this.ctx = ctx;
18089
18164
  this.crypto = crypto;
18090
18165
  }
18166
+ ctx;
18167
+ crypto;
18091
18168
  /**
18092
18169
  * Estimates the gas cost for a solver to fill the given order and returns
18093
18170
  * a structured estimate with individual gas components and total costs in
@@ -18509,6 +18586,7 @@ var OrderStatusChecker = class {
18509
18586
  constructor(ctx) {
18510
18587
  this.ctx = ctx;
18511
18588
  }
18589
+ ctx;
18512
18590
  /**
18513
18591
  * Checks if a V2 order has been filled by reading the commitment storage slot on the destination chain.
18514
18592
  *
@@ -18690,7 +18768,7 @@ var IntentGateway = class _IntentGateway {
18690
18768
  * The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
18691
18769
  * 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
18692
18770
  * the `OrderPlaced` event is confirmed.
18693
- * 4. Delegates to {@link OrderExecutor.executeIntentOrder} and forwards all
18771
+ * 4. Delegates to {@link OrderExecutor.executeOrder} and forwards all
18694
18772
  * subsequent status updates until the order is filled, exhausted, or fails.
18695
18773
  *
18696
18774
  * @param order - The order to place and execute. `order.fees` may be 0; it
@@ -18700,8 +18778,7 @@ var IntentGateway = class _IntentGateway {
18700
18778
  * @param options - Optional tuning parameters:
18701
18779
  * - `maxPriorityFeePerGasBumpPercent` — bump % for the priority fee estimate (default 8).
18702
18780
  * - `maxFeePerGasBumpPercent` — bump % for the max fee estimate (default 10).
18703
- * - `minBids` — minimum bids to collect before selecting (default 1).
18704
- * - `bidTimeoutMs` — how long to poll for bids before giving up (default 60 000 ms).
18781
+ * - `auctionTimeMs` — duration in ms to collect bids before selecting the best one.
18705
18782
  * - `pollIntervalMs` — interval between bid-polling attempts.
18706
18783
  * @yields {@link IntentOrderStatusUpdate} at each lifecycle stage.
18707
18784
  * @throws If the `placeOrder` generator behaves unexpectedly, or if gas
@@ -18734,18 +18811,63 @@ var IntentGateway = class _IntentGateway {
18734
18811
  }
18735
18812
  const { order: finalizedOrder, receipt: placementReceipt } = placeOrderSecond.value;
18736
18813
  yield { status: "ORDER_PLACED", order: finalizedOrder, receipt: placementReceipt };
18737
- for await (const status of this.orderExecutor.executeIntentOrder({
18814
+ for await (const status of this.orderExecutor.executeOrder({
18738
18815
  order: finalizedOrder,
18739
18816
  sessionPrivateKey,
18740
- minBids: options?.minBids,
18741
- bidTimeoutMs: options?.bidTimeoutMs,
18742
- pollIntervalMs: options?.pollIntervalMs,
18743
- solver: options?.solver
18817
+ auctionTimeMs: options.auctionTimeMs,
18818
+ pollIntervalMs: options.pollIntervalMs,
18819
+ solver: options.solver
18744
18820
  })) {
18745
18821
  yield status;
18746
18822
  }
18747
18823
  return;
18748
18824
  }
18825
+ /**
18826
+ * Validates that an order has the minimum fields required for post-placement
18827
+ * resume (i.e. it was previously placed and has an on-chain identity).
18828
+ *
18829
+ * @throws If `order.id` or `order.session` is missing or zero-valued.
18830
+ */
18831
+ assertOrderCanResume(order) {
18832
+ if (!order.id) {
18833
+ throw new Error("Cannot resume execution without order.id");
18834
+ }
18835
+ if (!order.session || order.session === ADDRESS_ZERO2) {
18836
+ throw new Error("Cannot resume execution without order.session");
18837
+ }
18838
+ }
18839
+ /**
18840
+ * Resumes execution of a previously placed order.
18841
+ *
18842
+ * Use this method after an app restart or crash to pick up where
18843
+ * {@link execute} left off. The order must already be placed on-chain
18844
+ * (i.e. it must have a valid `id` and `session`).
18845
+ *
18846
+ * Internally delegates to {@link OrderExecutor.executeOrder} and
18847
+ * yields the same status updates as the execution phase of {@link execute}:
18848
+ * `AWAITING_BIDS`, `BIDS_RECEIVED`, `BID_SELECTED`,
18849
+ * `FILLED`, `PARTIAL_FILL`, `EXPIRED`, or `FAILED`.
18850
+ *
18851
+ * Callers may check {@link isOrderFilled} or {@link isOrderRefunded} before
18852
+ * calling this method to avoid resuming an already-terminal order.
18853
+ *
18854
+ * @param order - A previously placed order with a valid `id` and `session`.
18855
+ * @param options - Optional tuning parameters for bid collection and execution.
18856
+ * @yields {@link IntentOrderStatusUpdate} at each execution stage.
18857
+ * @throws If the order is missing required fields for resumption.
18858
+ */
18859
+ async *resume(order, options) {
18860
+ this.assertOrderCanResume(order);
18861
+ for await (const status of this.orderExecutor.executeOrder({
18862
+ order,
18863
+ sessionPrivateKey: options.sessionPrivateKey,
18864
+ auctionTimeMs: options.auctionTimeMs,
18865
+ pollIntervalMs: options.pollIntervalMs,
18866
+ solver: options.solver
18867
+ })) {
18868
+ yield status;
18869
+ }
18870
+ }
18749
18871
  /**
18750
18872
  * Returns both the native token cost and the relayer fee for cancelling an
18751
18873
  * order. Use `relayerFee` to approve the ERC-20 spend before submitting.