@hyperbridge/sdk 2.3.2 → 2.3.3

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.
@@ -7083,6 +7083,11 @@ var ExpectedError = class _ExpectedError extends Error {
7083
7083
  return error instanceof _ExpectedError;
7084
7084
  }
7085
7085
  };
7086
+
7087
+ // src/configs/constants.ts
7088
+ var ISMP_PREFIX = ":child_storage:default:ISMPv2";
7089
+
7090
+ // src/chains/substrate.ts
7086
7091
  var HttpRpcClient = class {
7087
7092
  constructor(url) {
7088
7093
  this.url = url;
@@ -7206,7 +7211,7 @@ var SubstrateChain = class _SubstrateChain {
7206
7211
  * @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
7207
7212
  */
7208
7213
  async queryRequestCommitment(commitment) {
7209
- const prefix = toHex(":child_storage:default:ISMP");
7214
+ const prefix = toHex(ISMP_PREFIX);
7210
7215
  const key = this.requestCommitmentKey(commitment);
7211
7216
  const item = await this.rpcClient.call("childstate_getStorage", [prefix, key]);
7212
7217
  return item;
@@ -7217,7 +7222,7 @@ var SubstrateChain = class _SubstrateChain {
7217
7222
  * @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
7218
7223
  */
7219
7224
  async queryRequestReceipt(commitment) {
7220
- const prefix = toHex(":child_storage:default:ISMP");
7225
+ const prefix = toHex(ISMP_PREFIX);
7221
7226
  const key = this.requestReceiptKey(commitment);
7222
7227
  const item = await this.rpcClient.call("childstate_getStorage", [prefix, key]);
7223
7228
  return item;
@@ -7241,7 +7246,7 @@ var SubstrateChain = class _SubstrateChain {
7241
7246
  * @returns {Promise<HexString | undefined>} The receipt data if present, otherwise undefined.
7242
7247
  */
7243
7248
  async queryResponseReceipt(commitment) {
7244
- const prefix = toHex(":child_storage:default:ISMP");
7249
+ const prefix = toHex(ISMP_PREFIX);
7245
7250
  const key = this.responseReceiptKey(commitment);
7246
7251
  const item = await this.rpcClient.call("childstate_getStorage", [prefix, key]);
7247
7252
  return item;
@@ -15359,7 +15364,11 @@ var OrderExecutor = class {
15359
15364
  */
15360
15365
  async fetchBids(params) {
15361
15366
  const { commitment, solver, solverLockStartTime } = params;
15362
- const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
15367
+ const intentsCoprocessor = this.ctx.intentsCoprocessor;
15368
+ if (!intentsCoprocessor) {
15369
+ throw new Error("IntentsCoprocessor required for order execution");
15370
+ }
15371
+ const fetchedBids = await intentsCoprocessor.getBidsForOrder(commitment);
15363
15372
  if (solver) {
15364
15373
  const { address, timeoutMs } = solver;
15365
15374
  const solverLockActive = Date.now() - solverLockStartTime < timeoutMs;
@@ -15448,7 +15457,7 @@ var OrderExecutor = class {
15448
15457
  * → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
15449
15458
  *
15450
15459
  * **Cross-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
15451
- * (terminates — settlement is confirmed async via Hyperbridge)
15460
+ * `FILLED`
15452
15461
  */
15453
15462
  async *executeOrder(options) {
15454
15463
  const { order, sessionPrivateKey, auctionTimeMs, pollIntervalMs = DEFAULT_POLL_INTERVAL, solver } = options;
@@ -15587,7 +15596,13 @@ var OrderExecutor = class {
15587
15596
  userOp: result.userOp,
15588
15597
  transactionHash: result.txnHash
15589
15598
  };
15590
- const fill = this.processFillResult(result, commitment, targetAssets, totalFilledAssets, remainingAssets);
15599
+ const fill = this.processFillResult(
15600
+ result,
15601
+ commitment,
15602
+ targetAssets,
15603
+ totalFilledAssets,
15604
+ remainingAssets
15605
+ );
15591
15606
  totalFilledAssets = fill.totalFilledAssets;
15592
15607
  remainingAssets = fill.remainingAssets;
15593
15608
  if (fill.update) {
@@ -15613,6 +15628,10 @@ var OrderCanceller = class {
15613
15628
  this.ctx = ctx;
15614
15629
  }
15615
15630
  ctx;
15631
+ logger = createConsola({
15632
+ level: LogLevels.info,
15633
+ formatOptions: { columns: 80, colors: true, compact: true, date: false }
15634
+ }).withTag("[OrderCanceller]");
15616
15635
  /**
15617
15636
  * Returns both the native token cost and the relayer fee for cancelling an
15618
15637
  * order. Frontends can use `relayerFee` to approve the ERC-20 spend before
@@ -16028,32 +16047,55 @@ var OrderCanceller = class {
16028
16047
  }
16029
16048
  /**
16030
16049
  * Submits an unsigned GET request message to Hyperbridge and waits until
16031
- * the request receipt is confirmed on-chain.
16050
+ * the GET response receipt is confirmed on-chain.
16032
16051
  *
16033
- * If the initial submission fails, the method waits 30 seconds and then
16034
- * retries querying for the receipt up to 10 times with 5-second back-off.
16052
+ * GET handling on Hyperbridge creates a response receipt keyed by the
16053
+ * request commitment. That receipt is the durable delivery signal, so a
16054
+ * duplicate unsigned submission is considered successful only if the
16055
+ * response receipt can be observed.
16035
16056
  *
16036
16057
  * @param hyperbridge - Hyperbridge Substrate chain client.
16037
16058
  * @param commitment - The GET request commitment hash used to poll for the receipt.
16038
16059
  * @param message - The fully constructed GET request message to submit.
16039
16060
  */
16040
16061
  async submitAndConfirmReceipt(hyperbridge, commitment, message) {
16041
- let storageValue = await hyperbridge.queryRequestReceipt(commitment);
16042
- if (!storageValue) {
16043
- try {
16044
- await hyperbridge.submitUnsigned(message);
16045
- } catch {
16046
- }
16062
+ this.logger.info(`Checking GET response receipt before Hyperbridge delivery (${commitment})`);
16063
+ if (await this.queryDeliveredReceipt(hyperbridge, commitment)) {
16064
+ this.logger.info(`GET ${commitment} already delivered to Hyperbridge; skipping unsigned submission`);
16065
+ return;
16066
+ }
16067
+ try {
16068
+ this.logger.info(`Submitting unsigned GET ${commitment} to Hyperbridge`);
16069
+ await hyperbridge.submitUnsigned(message);
16070
+ this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
16047
16071
  await sleep(3e4);
16048
- storageValue = await retryPromise(
16049
- async () => {
16050
- const value = await hyperbridge.queryRequestReceipt(commitment);
16051
- if (!value) throw new Error("Receipt not found");
16052
- return value;
16053
- },
16054
- { maxRetries: 10, backoffMs: 5e3, logMessage: "Checking for receipt" }
16072
+ } catch (error) {
16073
+ this.logger.warn(
16074
+ `Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
16055
16075
  );
16056
16076
  }
16077
+ try {
16078
+ await this.pollDeliveredReceipt(hyperbridge, commitment);
16079
+ this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
16080
+ } catch (error) {
16081
+ const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
16082
+ this.logger.error(message2);
16083
+ throw new Error(message2);
16084
+ }
16085
+ }
16086
+ async queryDeliveredReceipt(hyperbridge, commitment) {
16087
+ return hyperbridge.queryResponseReceipt(commitment);
16088
+ }
16089
+ async pollDeliveredReceipt(hyperbridge, commitment) {
16090
+ this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
16091
+ return retryPromise(
16092
+ async () => {
16093
+ const value = await this.queryDeliveredReceipt(hyperbridge, commitment);
16094
+ if (!value) throw new Error(`GET response receipt not found for ${commitment}`);
16095
+ return value;
16096
+ },
16097
+ { maxRetries: 10, backoffMs: 5e3, logMessage: `Checking GET response receipt ${commitment}` }
16098
+ );
16057
16099
  }
16058
16100
  /**
16059
16101
  * Estimates the relayer fee for delivering a POST from dest to source.
@@ -16124,7 +16166,7 @@ var BidImpl = class {
16124
16166
  const sessionKeyAddress = this.order.session;
16125
16167
  const sessionKeyData = this.sessionPrivateKey ? { privateKey: this.sessionPrivateKey } : await this.ctx.sessionKeyStorage.getSessionKeyByAddress(sessionKeyAddress);
16126
16168
  if (!sessionKeyData) {
16127
- throw new Error("SessionKey not found for commitment: " + commitment);
16169
+ throw new Error(`SessionKey not found for commitment: ${commitment}`);
16128
16170
  }
16129
16171
  const signature = await CryptoUtils.signSolverSelection(
16130
16172
  commitment,
@@ -16184,8 +16226,8 @@ var BidImpl = class {
16184
16226
  /**
16185
16227
  * Signs the `SelectSolver` message with the session key, appends it to the
16186
16228
  * solver's existing UserOp signature, and submits the UserOperation to the
16187
- * bundler. For same-chain orders, waits for the receipt and reads
16188
- * `OrderFilled` / `PartialFill` logs to determine fill status.
16229
+ * bundler. Waits for the receipt and reads `OrderFilled` / `PartialFill`
16230
+ * logs to determine fill status.
16189
16231
  *
16190
16232
  * @returns A {@link SelectBidResult} with the submitted UserOperation, its hash,
16191
16233
  * the solver address, transaction hash, and fill status.
@@ -16225,33 +16267,31 @@ var BidImpl = class {
16225
16267
  { maxRetries: 5, backoffMs: 2e3, logMessage: "Fetching user operation receipt" }
16226
16268
  );
16227
16269
  txnHash = receipt.receipt.transactionHash;
16228
- if (this.order.source === this.order.destination) {
16229
- try {
16230
- const chainReceipt = await this.ctx.dest.client.waitForTransactionReceipt({
16231
- hash: txnHash,
16232
- confirmations: 1
16233
- });
16234
- const events = parseEventLogs({
16235
- abi: ABI3,
16236
- logs: chainReceipt.logs,
16237
- eventName: ["OrderFilled", "PartialFill"]
16238
- });
16239
- const matched = events.find((e) => {
16240
- if (e.eventName === "OrderFilled")
16241
- return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16242
- if (e.eventName === "PartialFill")
16243
- return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16244
- return false;
16245
- });
16246
- if (matched?.eventName === "OrderFilled") {
16247
- fillStatus = "full";
16248
- } else if (matched?.eventName === "PartialFill") {
16249
- fillStatus = "partial";
16250
- filledAssets = matched.args.outputs ?? [];
16251
- }
16252
- } catch {
16253
- throw new Error("Failed to determine fill status from logs");
16270
+ try {
16271
+ const chainReceipt = await this.ctx.dest.client.waitForTransactionReceipt({
16272
+ hash: txnHash,
16273
+ confirmations: 1
16274
+ });
16275
+ const events = parseEventLogs({
16276
+ abi: ABI3,
16277
+ logs: chainReceipt.logs,
16278
+ eventName: ["OrderFilled", "PartialFill"]
16279
+ });
16280
+ const matched = events.find((e) => {
16281
+ if (e.eventName === "OrderFilled")
16282
+ return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16283
+ if (e.eventName === "PartialFill")
16284
+ return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16285
+ return false;
16286
+ });
16287
+ if (matched?.eventName === "OrderFilled") {
16288
+ fillStatus = "full";
16289
+ } else if (matched?.eventName === "PartialFill") {
16290
+ fillStatus = "partial";
16291
+ filledAssets = matched.args.outputs ?? [];
16254
16292
  }
16293
+ } catch {
16294
+ throw new Error("Failed to determine fill status from logs");
16255
16295
  }
16256
16296
  } catch (err) {
16257
16297
  throw new Error(`Failed to execute bid: ${err instanceof Error ? err.message : String(err)}`);