@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.
@@ -7033,6 +7033,11 @@ var ExpectedError = class _ExpectedError extends Error {
7033
7033
  return error instanceof _ExpectedError;
7034
7034
  }
7035
7035
  };
7036
+
7037
+ // src/configs/constants.ts
7038
+ var ISMP_PREFIX = ":child_storage:default:ISMPv2";
7039
+
7040
+ // src/chains/substrate.ts
7036
7041
  var HttpRpcClient = class {
7037
7042
  constructor(url) {
7038
7043
  this.url = url;
@@ -7156,7 +7161,7 @@ var SubstrateChain = class _SubstrateChain {
7156
7161
  * @returns {Promise<HexString | undefined>} The commitment data if found, undefined otherwise.
7157
7162
  */
7158
7163
  async queryRequestCommitment(commitment) {
7159
- const prefix = toHex(":child_storage:default:ISMP");
7164
+ const prefix = toHex(ISMP_PREFIX);
7160
7165
  const key = this.requestCommitmentKey(commitment);
7161
7166
  const item = await this.rpcClient.call("childstate_getStorage", [prefix, key]);
7162
7167
  return item;
@@ -7167,7 +7172,7 @@ var SubstrateChain = class _SubstrateChain {
7167
7172
  * @returns {Promise<HexString | undefined>} The relayer address responsible for delivering the request.
7168
7173
  */
7169
7174
  async queryRequestReceipt(commitment) {
7170
- const prefix = toHex(":child_storage:default:ISMP");
7175
+ const prefix = toHex(ISMP_PREFIX);
7171
7176
  const key = this.requestReceiptKey(commitment);
7172
7177
  const item = await this.rpcClient.call("childstate_getStorage", [prefix, key]);
7173
7178
  return item;
@@ -7191,7 +7196,7 @@ var SubstrateChain = class _SubstrateChain {
7191
7196
  * @returns {Promise<HexString | undefined>} The receipt data if present, otherwise undefined.
7192
7197
  */
7193
7198
  async queryResponseReceipt(commitment) {
7194
- const prefix = toHex(":child_storage:default:ISMP");
7199
+ const prefix = toHex(ISMP_PREFIX);
7195
7200
  const key = this.responseReceiptKey(commitment);
7196
7201
  const item = await this.rpcClient.call("childstate_getStorage", [prefix, key]);
7197
7202
  return item;
@@ -15299,7 +15304,11 @@ var OrderExecutor = class {
15299
15304
  */
15300
15305
  async fetchBids(params) {
15301
15306
  const { commitment, solver, solverLockStartTime } = params;
15302
- const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
15307
+ const intentsCoprocessor = this.ctx.intentsCoprocessor;
15308
+ if (!intentsCoprocessor) {
15309
+ throw new Error("IntentsCoprocessor required for order execution");
15310
+ }
15311
+ const fetchedBids = await intentsCoprocessor.getBidsForOrder(commitment);
15303
15312
  if (solver) {
15304
15313
  const { address, timeoutMs } = solver;
15305
15314
  const solverLockActive = Date.now() - solverLockStartTime < timeoutMs;
@@ -15388,7 +15397,7 @@ var OrderExecutor = class {
15388
15397
  * → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
15389
15398
  *
15390
15399
  * **Cross-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
15391
- * (terminates — settlement is confirmed async via Hyperbridge)
15400
+ * `FILLED`
15392
15401
  */
15393
15402
  async *executeOrder(options) {
15394
15403
  const { order, sessionPrivateKey, auctionTimeMs, pollIntervalMs = DEFAULT_POLL_INTERVAL, solver } = options;
@@ -15527,7 +15536,13 @@ var OrderExecutor = class {
15527
15536
  userOp: result.userOp,
15528
15537
  transactionHash: result.txnHash
15529
15538
  };
15530
- const fill = this.processFillResult(result, commitment, targetAssets, totalFilledAssets, remainingAssets);
15539
+ const fill = this.processFillResult(
15540
+ result,
15541
+ commitment,
15542
+ targetAssets,
15543
+ totalFilledAssets,
15544
+ remainingAssets
15545
+ );
15531
15546
  totalFilledAssets = fill.totalFilledAssets;
15532
15547
  remainingAssets = fill.remainingAssets;
15533
15548
  if (fill.update) {
@@ -15553,6 +15568,10 @@ var OrderCanceller = class {
15553
15568
  this.ctx = ctx;
15554
15569
  }
15555
15570
  ctx;
15571
+ logger = createConsola({
15572
+ level: LogLevels.info,
15573
+ formatOptions: { columns: 80, colors: true, compact: true, date: false }
15574
+ }).withTag("[OrderCanceller]");
15556
15575
  /**
15557
15576
  * Returns both the native token cost and the relayer fee for cancelling an
15558
15577
  * order. Frontends can use `relayerFee` to approve the ERC-20 spend before
@@ -15968,32 +15987,55 @@ var OrderCanceller = class {
15968
15987
  }
15969
15988
  /**
15970
15989
  * Submits an unsigned GET request message to Hyperbridge and waits until
15971
- * the request receipt is confirmed on-chain.
15990
+ * the GET response receipt is confirmed on-chain.
15972
15991
  *
15973
- * If the initial submission fails, the method waits 30 seconds and then
15974
- * retries querying for the receipt up to 10 times with 5-second back-off.
15992
+ * GET handling on Hyperbridge creates a response receipt keyed by the
15993
+ * request commitment. That receipt is the durable delivery signal, so a
15994
+ * duplicate unsigned submission is considered successful only if the
15995
+ * response receipt can be observed.
15975
15996
  *
15976
15997
  * @param hyperbridge - Hyperbridge Substrate chain client.
15977
15998
  * @param commitment - The GET request commitment hash used to poll for the receipt.
15978
15999
  * @param message - The fully constructed GET request message to submit.
15979
16000
  */
15980
16001
  async submitAndConfirmReceipt(hyperbridge, commitment, message) {
15981
- let storageValue = await hyperbridge.queryRequestReceipt(commitment);
15982
- if (!storageValue) {
15983
- try {
15984
- await hyperbridge.submitUnsigned(message);
15985
- } catch {
15986
- }
16002
+ this.logger.info(`Checking GET response receipt before Hyperbridge delivery (${commitment})`);
16003
+ if (await this.queryDeliveredReceipt(hyperbridge, commitment)) {
16004
+ this.logger.info(`GET ${commitment} already delivered to Hyperbridge; skipping unsigned submission`);
16005
+ return;
16006
+ }
16007
+ try {
16008
+ this.logger.info(`Submitting unsigned GET ${commitment} to Hyperbridge`);
16009
+ await hyperbridge.submitUnsigned(message);
16010
+ this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
15987
16011
  await sleep(3e4);
15988
- storageValue = await retryPromise(
15989
- async () => {
15990
- const value = await hyperbridge.queryRequestReceipt(commitment);
15991
- if (!value) throw new Error("Receipt not found");
15992
- return value;
15993
- },
15994
- { maxRetries: 10, backoffMs: 5e3, logMessage: "Checking for receipt" }
16012
+ } catch (error) {
16013
+ this.logger.warn(
16014
+ `Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
15995
16015
  );
15996
16016
  }
16017
+ try {
16018
+ await this.pollDeliveredReceipt(hyperbridge, commitment);
16019
+ this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
16020
+ } catch (error) {
16021
+ const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
16022
+ this.logger.error(message2);
16023
+ throw new Error(message2);
16024
+ }
16025
+ }
16026
+ async queryDeliveredReceipt(hyperbridge, commitment) {
16027
+ return hyperbridge.queryResponseReceipt(commitment);
16028
+ }
16029
+ async pollDeliveredReceipt(hyperbridge, commitment) {
16030
+ this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
16031
+ return retryPromise(
16032
+ async () => {
16033
+ const value = await this.queryDeliveredReceipt(hyperbridge, commitment);
16034
+ if (!value) throw new Error(`GET response receipt not found for ${commitment}`);
16035
+ return value;
16036
+ },
16037
+ { maxRetries: 10, backoffMs: 5e3, logMessage: `Checking GET response receipt ${commitment}` }
16038
+ );
15997
16039
  }
15998
16040
  /**
15999
16041
  * Estimates the relayer fee for delivering a POST from dest to source.
@@ -16064,7 +16106,7 @@ var BidImpl = class {
16064
16106
  const sessionKeyAddress = this.order.session;
16065
16107
  const sessionKeyData = this.sessionPrivateKey ? { privateKey: this.sessionPrivateKey } : await this.ctx.sessionKeyStorage.getSessionKeyByAddress(sessionKeyAddress);
16066
16108
  if (!sessionKeyData) {
16067
- throw new Error("SessionKey not found for commitment: " + commitment);
16109
+ throw new Error(`SessionKey not found for commitment: ${commitment}`);
16068
16110
  }
16069
16111
  const signature = await CryptoUtils.signSolverSelection(
16070
16112
  commitment,
@@ -16124,8 +16166,8 @@ var BidImpl = class {
16124
16166
  /**
16125
16167
  * Signs the `SelectSolver` message with the session key, appends it to the
16126
16168
  * solver's existing UserOp signature, and submits the UserOperation to the
16127
- * bundler. For same-chain orders, waits for the receipt and reads
16128
- * `OrderFilled` / `PartialFill` logs to determine fill status.
16169
+ * bundler. Waits for the receipt and reads `OrderFilled` / `PartialFill`
16170
+ * logs to determine fill status.
16129
16171
  *
16130
16172
  * @returns A {@link SelectBidResult} with the submitted UserOperation, its hash,
16131
16173
  * the solver address, transaction hash, and fill status.
@@ -16165,33 +16207,31 @@ var BidImpl = class {
16165
16207
  { maxRetries: 5, backoffMs: 2e3, logMessage: "Fetching user operation receipt" }
16166
16208
  );
16167
16209
  txnHash = receipt.receipt.transactionHash;
16168
- if (this.order.source === this.order.destination) {
16169
- try {
16170
- const chainReceipt = await this.ctx.dest.client.waitForTransactionReceipt({
16171
- hash: txnHash,
16172
- confirmations: 1
16173
- });
16174
- const events = parseEventLogs({
16175
- abi: ABI3,
16176
- logs: chainReceipt.logs,
16177
- eventName: ["OrderFilled", "PartialFill"]
16178
- });
16179
- const matched = events.find((e) => {
16180
- if (e.eventName === "OrderFilled")
16181
- return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16182
- if (e.eventName === "PartialFill")
16183
- return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16184
- return false;
16185
- });
16186
- if (matched?.eventName === "OrderFilled") {
16187
- fillStatus = "full";
16188
- } else if (matched?.eventName === "PartialFill") {
16189
- fillStatus = "partial";
16190
- filledAssets = matched.args.outputs ?? [];
16191
- }
16192
- } catch {
16193
- throw new Error("Failed to determine fill status from logs");
16210
+ try {
16211
+ const chainReceipt = await this.ctx.dest.client.waitForTransactionReceipt({
16212
+ hash: txnHash,
16213
+ confirmations: 1
16214
+ });
16215
+ const events = parseEventLogs({
16216
+ abi: ABI3,
16217
+ logs: chainReceipt.logs,
16218
+ eventName: ["OrderFilled", "PartialFill"]
16219
+ });
16220
+ const matched = events.find((e) => {
16221
+ if (e.eventName === "OrderFilled")
16222
+ return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16223
+ if (e.eventName === "PartialFill")
16224
+ return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16225
+ return false;
16226
+ });
16227
+ if (matched?.eventName === "OrderFilled") {
16228
+ fillStatus = "full";
16229
+ } else if (matched?.eventName === "PartialFill") {
16230
+ fillStatus = "partial";
16231
+ filledAssets = matched.args.outputs ?? [];
16194
16232
  }
16233
+ } catch {
16234
+ throw new Error("Failed to determine fill status from logs");
16195
16235
  }
16196
16236
  } catch (err) {
16197
16237
  throw new Error(`Failed to execute bid: ${err instanceof Error ? err.message : String(err)}`);