@hyperbridge/sdk 2.3.2 → 2.4.0

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.
@@ -2335,6 +2335,57 @@ declare class CryptoUtils {
2335
2335
  * @returns The UserOperation hash as a hex string.
2336
2336
  */
2337
2337
  static computeUserOpHash(userOp: PackedUserOperation, entryPoint: Hex, chainId: bigint): Hex;
2338
+ /**
2339
+ * Derives the ERC-4337 nonce key that binds a bid UserOperation to its
2340
+ * order and session key: the lower 192 bits of
2341
+ * `keccak256(commitment ‖ sessionKey)`. `SolverAccount` rejects bid
2342
+ * operations whose nonce key differs — this is what lets the solver sign
2343
+ * the plain userOpHash while staying committed to the order and to the
2344
+ * session key it bid against.
2345
+ *
2346
+ * @param commitment - The order commitment (`order.id`).
2347
+ * @param sessionKey - The order's session key address (`order.session`).
2348
+ * @returns The 192-bit nonce key as a bigint (pass to `EntryPoint.getNonce`).
2349
+ */
2350
+ static bidNonceKey(commitment: HexString, sessionKey: HexString): bigint;
2351
+ /**
2352
+ * Builds the EIP-712 typed-data payload whose digest is the EntryPoint v0.8
2353
+ * `userOpHash` (i.e. `hashTypedData(packedUserOpTypedData(...)) ===
2354
+ * computeUserOpHash(...)`). Signing this typed data is bit-identical to
2355
+ * signing the raw userOpHash, but keeps the full operation visible to
2356
+ * signing infrastructure (hardware wallets, MPC/TEE policy engines) instead
2357
+ * of an opaque 32-byte digest.
2358
+ *
2359
+ * @param userOp - The packed UserOperation to sign (signature field ignored).
2360
+ * @param entryPoint - Address of the EntryPoint v0.8 contract.
2361
+ * @param chainId - Chain ID of the network on which the operation will execute.
2362
+ * @returns A viem `TypedDataDefinition` for the operation.
2363
+ */
2364
+ static packedUserOpTypedData(userOp: PackedUserOperation, entryPoint: Hex, chainId: bigint): {
2365
+ domain: {
2366
+ name: string;
2367
+ version: string;
2368
+ chainId: bigint;
2369
+ verifyingContract: `0x${string}`;
2370
+ };
2371
+ types: {
2372
+ PackedUserOperation: {
2373
+ name: string;
2374
+ type: string;
2375
+ }[];
2376
+ };
2377
+ primaryType: "PackedUserOperation";
2378
+ message: {
2379
+ sender: `0x${string}`;
2380
+ nonce: bigint;
2381
+ initCode: `0x${string}`;
2382
+ callData: `0x${string}`;
2383
+ accountGasLimits: `0x${string}`;
2384
+ preVerificationGas: bigint;
2385
+ gasFees: `0x${string}`;
2386
+ paymasterAndData: `0x${string}`;
2387
+ };
2388
+ };
2338
2389
  /**
2339
2390
  * Computes the EIP-712 struct hash of a `PackedUserOperation`.
2340
2391
  *
@@ -2335,6 +2335,57 @@ declare class CryptoUtils {
2335
2335
  * @returns The UserOperation hash as a hex string.
2336
2336
  */
2337
2337
  static computeUserOpHash(userOp: PackedUserOperation, entryPoint: Hex, chainId: bigint): Hex;
2338
+ /**
2339
+ * Derives the ERC-4337 nonce key that binds a bid UserOperation to its
2340
+ * order and session key: the lower 192 bits of
2341
+ * `keccak256(commitment ‖ sessionKey)`. `SolverAccount` rejects bid
2342
+ * operations whose nonce key differs — this is what lets the solver sign
2343
+ * the plain userOpHash while staying committed to the order and to the
2344
+ * session key it bid against.
2345
+ *
2346
+ * @param commitment - The order commitment (`order.id`).
2347
+ * @param sessionKey - The order's session key address (`order.session`).
2348
+ * @returns The 192-bit nonce key as a bigint (pass to `EntryPoint.getNonce`).
2349
+ */
2350
+ static bidNonceKey(commitment: HexString, sessionKey: HexString): bigint;
2351
+ /**
2352
+ * Builds the EIP-712 typed-data payload whose digest is the EntryPoint v0.8
2353
+ * `userOpHash` (i.e. `hashTypedData(packedUserOpTypedData(...)) ===
2354
+ * computeUserOpHash(...)`). Signing this typed data is bit-identical to
2355
+ * signing the raw userOpHash, but keeps the full operation visible to
2356
+ * signing infrastructure (hardware wallets, MPC/TEE policy engines) instead
2357
+ * of an opaque 32-byte digest.
2358
+ *
2359
+ * @param userOp - The packed UserOperation to sign (signature field ignored).
2360
+ * @param entryPoint - Address of the EntryPoint v0.8 contract.
2361
+ * @param chainId - Chain ID of the network on which the operation will execute.
2362
+ * @returns A viem `TypedDataDefinition` for the operation.
2363
+ */
2364
+ static packedUserOpTypedData(userOp: PackedUserOperation, entryPoint: Hex, chainId: bigint): {
2365
+ domain: {
2366
+ name: string;
2367
+ version: string;
2368
+ chainId: bigint;
2369
+ verifyingContract: `0x${string}`;
2370
+ };
2371
+ types: {
2372
+ PackedUserOperation: {
2373
+ name: string;
2374
+ type: string;
2375
+ }[];
2376
+ };
2377
+ primaryType: "PackedUserOperation";
2378
+ message: {
2379
+ sender: `0x${string}`;
2380
+ nonce: bigint;
2381
+ initCode: `0x${string}`;
2382
+ callData: `0x${string}`;
2383
+ accountGasLimits: `0x${string}`;
2384
+ preVerificationGas: bigint;
2385
+ gasFees: `0x${string}`;
2386
+ paymasterAndData: `0x${string}`;
2387
+ };
2388
+ };
2338
2389
  /**
2339
2390
  * Computes the EIP-712 struct hash of a `PackedUserOperation`.
2340
2391
  *
@@ -2585,7 +2585,7 @@ var chainConfigs = {
2585
2585
  UniswapV3Quoter: "0x0000000000000000000000000000000000000000",
2586
2586
  UniswapV4Quoter: "0x0000000000000000000000000000000000000000",
2587
2587
  EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
2588
- SolverAccount: "0x07FeC66d967800998060194EaECDd7C66dA4a1B1"
2588
+ SolverAccount: "0x110C7E1814c923127469Ca8939a12dAa70B96a17"
2589
2589
  },
2590
2590
  rpcEnvKey: "BSC_CHAPEL",
2591
2591
  defaultRpcUrl: "https://bnb-testnet.api.onfinality.io/public",
@@ -2693,7 +2693,7 @@ var chainConfigs = {
2693
2693
  },
2694
2694
  addresses: {
2695
2695
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2696
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2696
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
2697
2697
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2698
2698
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2699
2699
  UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
@@ -2748,7 +2748,7 @@ var chainConfigs = {
2748
2748
  },
2749
2749
  addresses: {
2750
2750
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2751
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2751
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
2752
2752
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2753
2753
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2754
2754
  UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
@@ -2804,7 +2804,7 @@ var chainConfigs = {
2804
2804
  },
2805
2805
  addresses: {
2806
2806
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2807
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2807
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
2808
2808
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2809
2809
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2810
2810
  UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
@@ -2861,7 +2861,7 @@ var chainConfigs = {
2861
2861
  },
2862
2862
  addresses: {
2863
2863
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2864
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2864
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
2865
2865
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2866
2866
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2867
2867
  UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
@@ -2920,7 +2920,7 @@ var chainConfigs = {
2920
2920
  },
2921
2921
  addresses: {
2922
2922
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2923
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2923
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
2924
2924
  TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
2925
2925
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2926
2926
  UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
@@ -3007,7 +3007,7 @@ var chainConfigs = {
3007
3007
  Calldispatcher: "0x876F1891982E260026630c233A4897160A281Fb8",
3008
3008
  Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
3009
3009
  EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
3010
- SolverAccount: "0x07FeC66d967800998060194EaECDd7C66dA4a1B1"
3010
+ SolverAccount: "0x110C7E1814c923127469Ca8939a12dAa70B96a17"
3011
3011
  },
3012
3012
  rpcEnvKey: "POLYGON_AMOY",
3013
3013
  defaultRpcUrl: "https://rpc-amoy.polygon.technology",
@@ -3031,7 +3031,7 @@ var chainConfigs = {
3031
3031
  },
3032
3032
  addresses: {
3033
3033
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
3034
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
3034
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
3035
3035
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
3036
3036
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
3037
3037
  UniswapRouter02: "0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2",
@@ -3066,7 +3066,7 @@ var chainConfigs = {
3066
3066
  },
3067
3067
  addresses: {
3068
3068
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
3069
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
3069
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
3070
3070
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
3071
3071
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
3072
3072
  UniswapRouter02: "0xB2e26652e4BAd1e56055A051f922E06760cA0BFE",
@@ -3221,7 +3221,7 @@ var chainConfigs = {
3221
3221
  },
3222
3222
  addresses: {
3223
3223
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
3224
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
3224
+ SolverAccount: "0x3bdB532d91F165BeFad5542700205f5BB5152a82",
3225
3225
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
3226
3226
  Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
3227
3227
  },
@@ -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;
@@ -14758,6 +14763,67 @@ var CryptoUtils = class _CryptoUtils {
14758
14763
  encodePacked(["bytes1", "bytes1", "bytes32", "bytes32"], ["0x19", "0x01", domainSeparator, structHash])
14759
14764
  );
14760
14765
  }
14766
+ /**
14767
+ * Derives the ERC-4337 nonce key that binds a bid UserOperation to its
14768
+ * order and session key: the lower 192 bits of
14769
+ * `keccak256(commitment ‖ sessionKey)`. `SolverAccount` rejects bid
14770
+ * operations whose nonce key differs — this is what lets the solver sign
14771
+ * the plain userOpHash while staying committed to the order and to the
14772
+ * session key it bid against.
14773
+ *
14774
+ * @param commitment - The order commitment (`order.id`).
14775
+ * @param sessionKey - The order's session key address (`order.session`).
14776
+ * @returns The 192-bit nonce key as a bigint (pass to `EntryPoint.getNonce`).
14777
+ */
14778
+ static bidNonceKey(commitment, sessionKey) {
14779
+ return BigInt(keccak256(encodePacked(["bytes32", "address"], [commitment, sessionKey]))) & (1n << 192n) - 1n;
14780
+ }
14781
+ /**
14782
+ * Builds the EIP-712 typed-data payload whose digest is the EntryPoint v0.8
14783
+ * `userOpHash` (i.e. `hashTypedData(packedUserOpTypedData(...)) ===
14784
+ * computeUserOpHash(...)`). Signing this typed data is bit-identical to
14785
+ * signing the raw userOpHash, but keeps the full operation visible to
14786
+ * signing infrastructure (hardware wallets, MPC/TEE policy engines) instead
14787
+ * of an opaque 32-byte digest.
14788
+ *
14789
+ * @param userOp - The packed UserOperation to sign (signature field ignored).
14790
+ * @param entryPoint - Address of the EntryPoint v0.8 contract.
14791
+ * @param chainId - Chain ID of the network on which the operation will execute.
14792
+ * @returns A viem `TypedDataDefinition` for the operation.
14793
+ */
14794
+ static packedUserOpTypedData(userOp, entryPoint, chainId) {
14795
+ return {
14796
+ domain: {
14797
+ name: "ERC4337",
14798
+ version: "1",
14799
+ chainId,
14800
+ verifyingContract: entryPoint
14801
+ },
14802
+ types: {
14803
+ PackedUserOperation: [
14804
+ { name: "sender", type: "address" },
14805
+ { name: "nonce", type: "uint256" },
14806
+ { name: "initCode", type: "bytes" },
14807
+ { name: "callData", type: "bytes" },
14808
+ { name: "accountGasLimits", type: "bytes32" },
14809
+ { name: "preVerificationGas", type: "uint256" },
14810
+ { name: "gasFees", type: "bytes32" },
14811
+ { name: "paymasterAndData", type: "bytes" }
14812
+ ]
14813
+ },
14814
+ primaryType: "PackedUserOperation",
14815
+ message: {
14816
+ sender: userOp.sender,
14817
+ nonce: userOp.nonce,
14818
+ initCode: userOp.initCode,
14819
+ callData: userOp.callData,
14820
+ accountGasLimits: userOp.accountGasLimits,
14821
+ preVerificationGas: userOp.preVerificationGas,
14822
+ gasFees: userOp.gasFees,
14823
+ paymasterAndData: userOp.paymasterAndData
14824
+ }
14825
+ };
14826
+ }
14761
14827
  /**
14762
14828
  * Computes the EIP-712 struct hash of a `PackedUserOperation`.
14763
14829
  *
@@ -15299,7 +15365,11 @@ var OrderExecutor = class {
15299
15365
  */
15300
15366
  async fetchBids(params) {
15301
15367
  const { commitment, solver, solverLockStartTime } = params;
15302
- const fetchedBids = await this.ctx.intentsCoprocessor.getBidsForOrder(commitment);
15368
+ const intentsCoprocessor = this.ctx.intentsCoprocessor;
15369
+ if (!intentsCoprocessor) {
15370
+ throw new Error("IntentsCoprocessor required for order execution");
15371
+ }
15372
+ const fetchedBids = await intentsCoprocessor.getBidsForOrder(commitment);
15303
15373
  if (solver) {
15304
15374
  const { address, timeoutMs } = solver;
15305
15375
  const solverLockActive = Date.now() - solverLockStartTime < timeoutMs;
@@ -15388,7 +15458,7 @@ var OrderExecutor = class {
15388
15458
  * → (`FILLED` | `PARTIAL_FILL`)* → (`FILLED` | `EXPIRED`)
15389
15459
  *
15390
15460
  * **Cross-chain:** `AWAITING_BIDS` → `BIDS_RECEIVED` → `BID_SELECTED`
15391
- * (terminates — settlement is confirmed async via Hyperbridge)
15461
+ * `FILLED`
15392
15462
  */
15393
15463
  async *executeOrder(options) {
15394
15464
  const { order, sessionPrivateKey, auctionTimeMs, pollIntervalMs = DEFAULT_POLL_INTERVAL, solver } = options;
@@ -15527,7 +15597,13 @@ var OrderExecutor = class {
15527
15597
  userOp: result.userOp,
15528
15598
  transactionHash: result.txnHash
15529
15599
  };
15530
- const fill = this.processFillResult(result, commitment, targetAssets, totalFilledAssets, remainingAssets);
15600
+ const fill = this.processFillResult(
15601
+ result,
15602
+ commitment,
15603
+ targetAssets,
15604
+ totalFilledAssets,
15605
+ remainingAssets
15606
+ );
15531
15607
  totalFilledAssets = fill.totalFilledAssets;
15532
15608
  remainingAssets = fill.remainingAssets;
15533
15609
  if (fill.update) {
@@ -15553,6 +15629,10 @@ var OrderCanceller = class {
15553
15629
  this.ctx = ctx;
15554
15630
  }
15555
15631
  ctx;
15632
+ logger = createConsola({
15633
+ level: LogLevels.info,
15634
+ formatOptions: { columns: 80, colors: true, compact: true, date: false }
15635
+ }).withTag("[OrderCanceller]");
15556
15636
  /**
15557
15637
  * Returns both the native token cost and the relayer fee for cancelling an
15558
15638
  * order. Frontends can use `relayerFee` to approve the ERC-20 spend before
@@ -15968,32 +16048,55 @@ var OrderCanceller = class {
15968
16048
  }
15969
16049
  /**
15970
16050
  * Submits an unsigned GET request message to Hyperbridge and waits until
15971
- * the request receipt is confirmed on-chain.
16051
+ * the GET response receipt is confirmed on-chain.
15972
16052
  *
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.
16053
+ * GET handling on Hyperbridge creates a response receipt keyed by the
16054
+ * request commitment. That receipt is the durable delivery signal, so a
16055
+ * duplicate unsigned submission is considered successful only if the
16056
+ * response receipt can be observed.
15975
16057
  *
15976
16058
  * @param hyperbridge - Hyperbridge Substrate chain client.
15977
16059
  * @param commitment - The GET request commitment hash used to poll for the receipt.
15978
16060
  * @param message - The fully constructed GET request message to submit.
15979
16061
  */
15980
16062
  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
- }
16063
+ this.logger.info(`Checking GET response receipt before Hyperbridge delivery (${commitment})`);
16064
+ if (await this.queryDeliveredReceipt(hyperbridge, commitment)) {
16065
+ this.logger.info(`GET ${commitment} already delivered to Hyperbridge; skipping unsigned submission`);
16066
+ return;
16067
+ }
16068
+ try {
16069
+ this.logger.info(`Submitting unsigned GET ${commitment} to Hyperbridge`);
16070
+ await hyperbridge.submitUnsigned(message);
16071
+ this.logger.info(`Unsigned GET ${commitment} submitted; waiting for Hyperbridge response receipt`);
15987
16072
  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" }
16073
+ } catch (error) {
16074
+ this.logger.warn(
16075
+ `Unsigned GET submit failed for ${commitment}; polling response receipt before failing: ${String(error)}`
15995
16076
  );
15996
16077
  }
16078
+ try {
16079
+ await this.pollDeliveredReceipt(hyperbridge, commitment);
16080
+ this.logger.info(`Confirmed Hyperbridge GET delivery for ${commitment}`);
16081
+ } catch (error) {
16082
+ const message2 = `Failed to deliver GET request to Hyperbridge; no response receipt found for ${commitment}: ${String(error)}`;
16083
+ this.logger.error(message2);
16084
+ throw new Error(message2);
16085
+ }
16086
+ }
16087
+ async queryDeliveredReceipt(hyperbridge, commitment) {
16088
+ return hyperbridge.queryResponseReceipt(commitment);
16089
+ }
16090
+ async pollDeliveredReceipt(hyperbridge, commitment) {
16091
+ this.logger.info(`Polling Hyperbridge GET response receipt for ${commitment}`);
16092
+ return retryPromise(
16093
+ async () => {
16094
+ const value = await this.queryDeliveredReceipt(hyperbridge, commitment);
16095
+ if (!value) throw new Error(`GET response receipt not found for ${commitment}`);
16096
+ return value;
16097
+ },
16098
+ { maxRetries: 10, backoffMs: 5e3, logMessage: `Checking GET response receipt ${commitment}` }
16099
+ );
15997
16100
  }
15998
16101
  /**
15999
16102
  * Estimates the relayer fee for delivering a POST from dest to source.
@@ -16064,7 +16167,7 @@ var BidImpl = class {
16064
16167
  const sessionKeyAddress = this.order.session;
16065
16168
  const sessionKeyData = this.sessionPrivateKey ? { privateKey: this.sessionPrivateKey } : await this.ctx.sessionKeyStorage.getSessionKeyByAddress(sessionKeyAddress);
16066
16169
  if (!sessionKeyData) {
16067
- throw new Error("SessionKey not found for commitment: " + commitment);
16170
+ throw new Error(`SessionKey not found for commitment: ${commitment}`);
16068
16171
  }
16069
16172
  const signature = await CryptoUtils.signSolverSelection(
16070
16173
  commitment,
@@ -16124,8 +16227,8 @@ var BidImpl = class {
16124
16227
  /**
16125
16228
  * Signs the `SelectSolver` message with the session key, appends it to the
16126
16229
  * 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.
16230
+ * bundler. Waits for the receipt and reads `OrderFilled` / `PartialFill`
16231
+ * logs to determine fill status.
16129
16232
  *
16130
16233
  * @returns A {@link SelectBidResult} with the submitted UserOperation, its hash,
16131
16234
  * the solver address, transaction hash, and fill status.
@@ -16165,33 +16268,31 @@ var BidImpl = class {
16165
16268
  { maxRetries: 5, backoffMs: 2e3, logMessage: "Fetching user operation receipt" }
16166
16269
  );
16167
16270
  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");
16271
+ try {
16272
+ const chainReceipt = await this.ctx.dest.client.waitForTransactionReceipt({
16273
+ hash: txnHash,
16274
+ confirmations: 1
16275
+ });
16276
+ const events = parseEventLogs({
16277
+ abi: ABI3,
16278
+ logs: chainReceipt.logs,
16279
+ eventName: ["OrderFilled", "PartialFill"]
16280
+ });
16281
+ const matched = events.find((e) => {
16282
+ if (e.eventName === "OrderFilled")
16283
+ return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16284
+ if (e.eventName === "PartialFill")
16285
+ return e.args.commitment.toLowerCase() === commitment.toLowerCase();
16286
+ return false;
16287
+ });
16288
+ if (matched?.eventName === "OrderFilled") {
16289
+ fillStatus = "full";
16290
+ } else if (matched?.eventName === "PartialFill") {
16291
+ fillStatus = "partial";
16292
+ filledAssets = matched.args.outputs ?? [];
16194
16293
  }
16294
+ } catch {
16295
+ throw new Error("Failed to determine fill status from logs");
16195
16296
  }
16196
16297
  } catch (err) {
16197
16298
  throw new Error(`Failed to execute bid: ${err instanceof Error ? err.message : String(err)}`);
@@ -16231,9 +16332,12 @@ var BidManager = class {
16231
16332
  * Constructs a signed `PackedUserOperation` that a solver can submit to the
16232
16333
  * Hyperbridge coprocessor as a bid to fill an order.
16233
16334
  *
16234
- * The solver's signature covers a hash that binds the UserOperation to the
16235
- * order commitment and the session key address, so the IntentGatewayV2
16236
- * contract can verify the solver's intent on-chain.
16335
+ * The solver signs the operation as EntryPoint v0.8 EIP-712 typed data,
16336
+ * whose digest is the plain userOpHash. The binding to the order lives in
16337
+ * the operation itself: the 4337 nonce key must be the lower 192 bits of
16338
+ * the order commitment (`SolverAccount` enforces this during validation),
16339
+ * and the callData carries the order. This keeps the signed payload fully
16340
+ * transparent to signing infrastructure instead of an opaque digest.
16237
16341
  *
16238
16342
  * @param options - Parameters describing the solver account, gas limits, fee
16239
16343
  * market values, and pre-built `callData` for the fill operation.
@@ -16271,10 +16375,17 @@ var BidManager = class {
16271
16375
  paymasterAndData,
16272
16376
  signature: "0x"
16273
16377
  };
16274
- const userOpHash = CryptoUtils.computeUserOpHash(userOp, entryPointAddress, chainId);
16275
- const sessionKey = order.session;
16276
- const messageHash = keccak256(concat([userOpHash, order.id, sessionKey]));
16277
- const solverSignature = await solverSigner.signMessage(messageHash, Number(chainId));
16378
+ const nonceKey = BigInt(nonce) >> 64n;
16379
+ const expectedKey = CryptoUtils.bidNonceKey(order.id, order.session);
16380
+ if (nonceKey !== expectedKey) {
16381
+ console.warn(
16382
+ `[BidManager] bid nonce key does not bind the order commitment and session key; on-chain validation will fail (order=${order.id})`
16383
+ );
16384
+ }
16385
+ const solverSignature = await solverSigner.signTypedData(
16386
+ CryptoUtils.packedUserOpTypedData(userOp, entryPointAddress, chainId),
16387
+ Number(chainId)
16388
+ );
16278
16389
  const signature = concat([order.id, solverSignature]);
16279
16390
  return { ...userOp, signature };
16280
16391
  }