@hyperbridge/sdk 2.3.3 → 2.4.2

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.
@@ -2490,30 +2490,30 @@ var handlerV2_default = { ABI: ABI2 };
2490
2490
  function tronAddress(base58) {
2491
2491
  return `0x${tronweb.TronWeb.address.toHex(base58).slice(2)}`;
2492
2492
  }
2493
- var Chains = /* @__PURE__ */ ((Chains3) => {
2494
- Chains3["BSC_CHAPEL"] = "EVM-97";
2495
- Chains3["GNOSIS_CHIADO"] = "EVM-10200";
2496
- Chains3["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
2497
- Chains3["SEPOLIA"] = "EVM-11155111";
2498
- Chains3["MAINNET"] = "EVM-1";
2499
- Chains3["BSC_MAINNET"] = "EVM-56";
2500
- Chains3["ARBITRUM_MAINNET"] = "EVM-42161";
2501
- Chains3["ARBITRUM_SEPOLIA"] = "EVM-421614";
2502
- Chains3["BASE_MAINNET"] = "EVM-8453";
2503
- Chains3["BASE_SEPOLIA"] = "EVM-84532";
2504
- Chains3["OPTIMISM_MAINNET"] = "EVM-10";
2505
- Chains3["OPTIMISM_SEPOLIA"] = "EVM-11155420";
2506
- Chains3["GNOSIS_MAINNET"] = "EVM-100";
2507
- Chains3["SONEIUM_MAINNET"] = "EVM-1868";
2508
- Chains3["POLYGON_MAINNET"] = "EVM-137";
2509
- Chains3["POLKADOT_HUB_MAINNET"] = "EVM-420420419";
2510
- Chains3["POLYGON_AMOY"] = "EVM-80002";
2511
- Chains3["POLKADOT_ASSET_HUB_PASEO"] = "EVM-420420417";
2512
- Chains3["TRON_MAINNET"] = "EVM-728126428";
2513
- Chains3["TRON_NILE"] = "EVM-3448148188";
2514
- Chains3["PHAROS_MAINNET"] = "EVM-688600";
2515
- Chains3["PHAROS_ATLANTIC"] = "EVM-688689";
2516
- return Chains3;
2493
+ var Chains = /* @__PURE__ */ ((Chains2) => {
2494
+ Chains2["BSC_CHAPEL"] = "EVM-97";
2495
+ Chains2["GNOSIS_CHIADO"] = "EVM-10200";
2496
+ Chains2["HYPERBRIDGE_GARGANTUA"] = "KUSAMA-4009";
2497
+ Chains2["SEPOLIA"] = "EVM-11155111";
2498
+ Chains2["MAINNET"] = "EVM-1";
2499
+ Chains2["BSC_MAINNET"] = "EVM-56";
2500
+ Chains2["ARBITRUM_MAINNET"] = "EVM-42161";
2501
+ Chains2["ARBITRUM_SEPOLIA"] = "EVM-421614";
2502
+ Chains2["BASE_MAINNET"] = "EVM-8453";
2503
+ Chains2["BASE_SEPOLIA"] = "EVM-84532";
2504
+ Chains2["OPTIMISM_MAINNET"] = "EVM-10";
2505
+ Chains2["OPTIMISM_SEPOLIA"] = "EVM-11155420";
2506
+ Chains2["GNOSIS_MAINNET"] = "EVM-100";
2507
+ Chains2["SONEIUM_MAINNET"] = "EVM-1868";
2508
+ Chains2["POLYGON_MAINNET"] = "EVM-137";
2509
+ Chains2["POLKADOT_HUB_MAINNET"] = "EVM-420420419";
2510
+ Chains2["POLYGON_AMOY"] = "EVM-80002";
2511
+ Chains2["POLKADOT_ASSET_HUB_PASEO"] = "EVM-420420417";
2512
+ Chains2["TRON_MAINNET"] = "EVM-728126428";
2513
+ Chains2["TRON_NILE"] = "EVM-3448148188";
2514
+ Chains2["PHAROS_MAINNET"] = "EVM-688600";
2515
+ Chains2["PHAROS_ATLANTIC"] = "EVM-688689";
2516
+ return Chains2;
2517
2517
  })(Chains || {});
2518
2518
  var polkadotAssetHubPaseo = viem.defineChain({
2519
2519
  id: 420420417,
@@ -2596,7 +2596,7 @@ var chainConfigs = {
2596
2596
  UniswapV3Quoter: "0x0000000000000000000000000000000000000000",
2597
2597
  UniswapV4Quoter: "0x0000000000000000000000000000000000000000",
2598
2598
  EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
2599
- SolverAccount: "0x07FeC66d967800998060194EaECDd7C66dA4a1B1"
2599
+ SolverAccount: "0x110C7E1814c923127469Ca8939a12dAa70B96a17"
2600
2600
  },
2601
2601
  rpcEnvKey: "BSC_CHAPEL",
2602
2602
  defaultRpcUrl: "https://bnb-testnet.api.onfinality.io/public",
@@ -2704,7 +2704,7 @@ var chainConfigs = {
2704
2704
  },
2705
2705
  addresses: {
2706
2706
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2707
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2707
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
2708
2708
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2709
2709
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2710
2710
  UniswapRouter02: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
@@ -2759,7 +2759,7 @@ var chainConfigs = {
2759
2759
  },
2760
2760
  addresses: {
2761
2761
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2762
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2762
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
2763
2763
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2764
2764
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2765
2765
  UniswapRouter02: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
@@ -2815,7 +2815,7 @@ var chainConfigs = {
2815
2815
  },
2816
2816
  addresses: {
2817
2817
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2818
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2818
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
2819
2819
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2820
2820
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2821
2821
  UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
@@ -2872,7 +2872,7 @@ var chainConfigs = {
2872
2872
  },
2873
2873
  addresses: {
2874
2874
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2875
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2875
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
2876
2876
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
2877
2877
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2878
2878
  UniswapRouter02: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
@@ -2931,7 +2931,7 @@ var chainConfigs = {
2931
2931
  },
2932
2932
  addresses: {
2933
2933
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
2934
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
2934
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
2935
2935
  TokenGateway: "0x8b536105b6Fae2aE9199f5146D3C57Dfe53b614E",
2936
2936
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
2937
2937
  UniswapRouter02: "0xd2f9496824951D5237cC71245D659E48d0d5f9E8",
@@ -3018,7 +3018,7 @@ var chainConfigs = {
3018
3018
  Calldispatcher: "0x876F1891982E260026630c233A4897160A281Fb8",
3019
3019
  Permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3",
3020
3020
  EntryPointV08: "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108",
3021
- SolverAccount: "0x07FeC66d967800998060194EaECDd7C66dA4a1B1"
3021
+ SolverAccount: "0x110C7E1814c923127469Ca8939a12dAa70B96a17"
3022
3022
  },
3023
3023
  rpcEnvKey: "POLYGON_AMOY",
3024
3024
  defaultRpcUrl: "https://rpc-amoy.polygon.technology",
@@ -3042,7 +3042,7 @@ var chainConfigs = {
3042
3042
  },
3043
3043
  addresses: {
3044
3044
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
3045
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
3045
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
3046
3046
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
3047
3047
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
3048
3048
  UniswapRouter02: "0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2",
@@ -3077,7 +3077,7 @@ var chainConfigs = {
3077
3077
  },
3078
3078
  addresses: {
3079
3079
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
3080
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
3080
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
3081
3081
  TokenGateway: "0xFd413e3AFe560182C4471F4d143A96d3e259B6dE",
3082
3082
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
3083
3083
  UniswapRouter02: "0xB2e26652e4BAd1e56055A051f922E06760cA0BFE",
@@ -3232,7 +3232,7 @@ var chainConfigs = {
3232
3232
  },
3233
3233
  addresses: {
3234
3234
  IntentGateway: "0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716",
3235
- SolverAccount: "0x975e80B476cB1d4Cd06c292ce36898f2bE4159ea",
3235
+ SolverAccount: "0xfCd233b937D7622AAc63ced3C9A1A12F4a6B64E3",
3236
3236
  Host: "0x620128E2B19193d6Bd244a3AC8D3bBa0541B19c3",
3237
3237
  Calldispatcher: "0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd"
3238
3238
  },
@@ -5118,6 +5118,24 @@ var ChainConfigService = class {
5118
5118
  getAssetAddress(chain, symbol) {
5119
5119
  return this.getConfig(chain)?.assets?.[symbol];
5120
5120
  }
5121
+ /**
5122
+ * Resolves configured token metadata from an address on a specific chain.
5123
+ * This is used by SDK helpers that accept token addresses rather than caller-
5124
+ * supplied symbols or decimals.
5125
+ */
5126
+ getAssetMetadataByAddress(chain, address) {
5127
+ const config = this.getConfig(chain);
5128
+ if (!config?.assets) return;
5129
+ const normalizedAddress = address.toLowerCase();
5130
+ for (const [symbol, configuredAddress] of Object.entries(config.assets)) {
5131
+ if (configuredAddress.toLowerCase() !== normalizedAddress) continue;
5132
+ return {
5133
+ symbol,
5134
+ address: configuredAddress,
5135
+ decimals: config.tokenDecimals?.[symbol]
5136
+ };
5137
+ }
5138
+ }
5121
5139
  getUsdtAsset(chain) {
5122
5140
  return this.getConfig(chain)?.assets?.USDT ?? "0x";
5123
5141
  }
@@ -7791,7 +7809,7 @@ var IntentsCoprocessor = class _IntentsCoprocessor {
7791
7809
  */
7792
7810
  async sendExtrinsicWithRetries(extrinsic, maxRetries, timeoutMs) {
7793
7811
  const keyPair = this.getKeyPair();
7794
- let baseTip = 500000000000n;
7812
+ const baseTip = 1000000000n;
7795
7813
  let attempt = 0;
7796
7814
  while (attempt < maxRetries) {
7797
7815
  const currentTip = baseTip * BigInt(2 ** attempt);
@@ -11461,6 +11479,33 @@ query OrderStatus($commitment: String!) {
11461
11479
  }
11462
11480
  }
11463
11481
  }`;
11482
+ var LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT = `
11483
+ query LatestPhantomOrderPriceSnapshot($tokenA: String!, $tokenB: String!) {
11484
+ phantomOrderPriceSnapshots(
11485
+ filter: {
11486
+ and: [
11487
+ { tokenA: { equalTo: $tokenA } }
11488
+ { tokenB: { equalTo: $tokenB } }
11489
+ { medianPrice: { isNull: false } }
11490
+ ]
11491
+ }
11492
+ orderBy: BLOCK_NUMBER_DESC
11493
+ first: 1
11494
+ ) {
11495
+ nodes {
11496
+ commitment
11497
+ tokenA
11498
+ tokenB
11499
+ standardAmount
11500
+ blockNumber
11501
+ medianPrice
11502
+ lowestPrice
11503
+ highestPrice
11504
+ bidCount
11505
+ snapshotTime
11506
+ }
11507
+ }
11508
+ }`;
11464
11509
  var TOKEN_GATEWAY_ASSET_TELEPORTED_STATUS = `
11465
11510
  query TokenGatewayAssetTeleportedStatus($commitment: String!) {
11466
11511
  tokenGatewayAssetTeleportedV2s(
@@ -11522,6 +11567,29 @@ async function queryAssetTeleported(params) {
11522
11567
  function queryGetRequest(params) {
11523
11568
  return _queryGetRequestInternal(params);
11524
11569
  }
11570
+ async function _queryLatestPhantomOrderPriceSnapshot(params) {
11571
+ const response = await params.queryClient.request(
11572
+ LATEST_PHANTOM_ORDER_PRICE_SNAPSHOT,
11573
+ {
11574
+ tokenA: params.tokenA.toLowerCase(),
11575
+ tokenB: params.tokenB.toLowerCase()
11576
+ }
11577
+ );
11578
+ const snapshot = response.phantomOrderPriceSnapshots.nodes[0];
11579
+ if (!snapshot?.medianPrice) return;
11580
+ return {
11581
+ commitment: snapshot.commitment,
11582
+ tokenA: snapshot.tokenA,
11583
+ tokenB: snapshot.tokenB,
11584
+ standardAmount: BigInt(snapshot.standardAmount),
11585
+ blockNumber: BigInt(snapshot.blockNumber),
11586
+ medianPrice: BigInt(snapshot.medianPrice),
11587
+ lowestPrice: snapshot.lowestPrice === null ? void 0 : BigInt(snapshot.lowestPrice),
11588
+ highestPrice: snapshot.highestPrice === null ? void 0 : BigInt(snapshot.highestPrice),
11589
+ bidCount: snapshot.bidCount,
11590
+ snapshotTime: new Date(snapshot.snapshotTime)
11591
+ };
11592
+ }
11525
11593
  async function _queryTokenGatewayAssetTeleportedInternal(params) {
11526
11594
  const { commitmentHash, queryClient: client, logger = DEFAULT_LOGGER } = params;
11527
11595
  const response = await retryPromise(
@@ -14774,6 +14842,67 @@ var CryptoUtils = class _CryptoUtils {
14774
14842
  viem.encodePacked(["bytes1", "bytes1", "bytes32", "bytes32"], ["0x19", "0x01", domainSeparator, structHash])
14775
14843
  );
14776
14844
  }
14845
+ /**
14846
+ * Derives the ERC-4337 nonce key that binds a bid UserOperation to its
14847
+ * order and session key: the lower 192 bits of
14848
+ * `keccak256(commitment ‖ sessionKey)`. `SolverAccount` rejects bid
14849
+ * operations whose nonce key differs — this is what lets the solver sign
14850
+ * the plain userOpHash while staying committed to the order and to the
14851
+ * session key it bid against.
14852
+ *
14853
+ * @param commitment - The order commitment (`order.id`).
14854
+ * @param sessionKey - The order's session key address (`order.session`).
14855
+ * @returns The 192-bit nonce key as a bigint (pass to `EntryPoint.getNonce`).
14856
+ */
14857
+ static bidNonceKey(commitment, sessionKey) {
14858
+ return BigInt(viem.keccak256(viem.encodePacked(["bytes32", "address"], [commitment, sessionKey]))) & (1n << 192n) - 1n;
14859
+ }
14860
+ /**
14861
+ * Builds the EIP-712 typed-data payload whose digest is the EntryPoint v0.8
14862
+ * `userOpHash` (i.e. `hashTypedData(packedUserOpTypedData(...)) ===
14863
+ * computeUserOpHash(...)`). Signing this typed data is bit-identical to
14864
+ * signing the raw userOpHash, but keeps the full operation visible to
14865
+ * signing infrastructure (hardware wallets, MPC/TEE policy engines) instead
14866
+ * of an opaque 32-byte digest.
14867
+ *
14868
+ * @param userOp - The packed UserOperation to sign (signature field ignored).
14869
+ * @param entryPoint - Address of the EntryPoint v0.8 contract.
14870
+ * @param chainId - Chain ID of the network on which the operation will execute.
14871
+ * @returns A viem `TypedDataDefinition` for the operation.
14872
+ */
14873
+ static packedUserOpTypedData(userOp, entryPoint, chainId) {
14874
+ return {
14875
+ domain: {
14876
+ name: "ERC4337",
14877
+ version: "1",
14878
+ chainId,
14879
+ verifyingContract: entryPoint
14880
+ },
14881
+ types: {
14882
+ PackedUserOperation: [
14883
+ { name: "sender", type: "address" },
14884
+ { name: "nonce", type: "uint256" },
14885
+ { name: "initCode", type: "bytes" },
14886
+ { name: "callData", type: "bytes" },
14887
+ { name: "accountGasLimits", type: "bytes32" },
14888
+ { name: "preVerificationGas", type: "uint256" },
14889
+ { name: "gasFees", type: "bytes32" },
14890
+ { name: "paymasterAndData", type: "bytes" }
14891
+ ]
14892
+ },
14893
+ primaryType: "PackedUserOperation",
14894
+ message: {
14895
+ sender: userOp.sender,
14896
+ nonce: userOp.nonce,
14897
+ initCode: userOp.initCode,
14898
+ callData: userOp.callData,
14899
+ accountGasLimits: userOp.accountGasLimits,
14900
+ preVerificationGas: userOp.preVerificationGas,
14901
+ gasFees: userOp.gasFees,
14902
+ paymasterAndData: userOp.paymasterAndData
14903
+ }
14904
+ };
14905
+ }
14777
14906
  /**
14778
14907
  * Computes the EIP-712 struct hash of a `PackedUserOperation`.
14779
14908
  *
@@ -16282,9 +16411,12 @@ var BidManager = class {
16282
16411
  * Constructs a signed `PackedUserOperation` that a solver can submit to the
16283
16412
  * Hyperbridge coprocessor as a bid to fill an order.
16284
16413
  *
16285
- * The solver's signature covers a hash that binds the UserOperation to the
16286
- * order commitment and the session key address, so the IntentGatewayV2
16287
- * contract can verify the solver's intent on-chain.
16414
+ * The solver signs the operation as EntryPoint v0.8 EIP-712 typed data,
16415
+ * whose digest is the plain userOpHash. The binding to the order lives in
16416
+ * the operation itself: the 4337 nonce key must be the lower 192 bits of
16417
+ * the order commitment (`SolverAccount` enforces this during validation),
16418
+ * and the callData carries the order. This keeps the signed payload fully
16419
+ * transparent to signing infrastructure instead of an opaque digest.
16288
16420
  *
16289
16421
  * @param options - Parameters describing the solver account, gas limits, fee
16290
16422
  * market values, and pre-built `callData` for the fill operation.
@@ -16322,10 +16454,17 @@ var BidManager = class {
16322
16454
  paymasterAndData,
16323
16455
  signature: "0x"
16324
16456
  };
16325
- const userOpHash = CryptoUtils.computeUserOpHash(userOp, entryPointAddress, chainId);
16326
- const sessionKey = order.session;
16327
- const messageHash = viem.keccak256(viem.concat([userOpHash, order.id, sessionKey]));
16328
- const solverSignature = await solverSigner.signMessage(messageHash, Number(chainId));
16457
+ const nonceKey = BigInt(nonce) >> 64n;
16458
+ const expectedKey = CryptoUtils.bidNonceKey(order.id, order.session);
16459
+ if (nonceKey !== expectedKey) {
16460
+ console.warn(
16461
+ `[BidManager] bid nonce key does not bind the order commitment and session key; on-chain validation will fail (order=${order.id})`
16462
+ );
16463
+ }
16464
+ const solverSignature = await solverSigner.signTypedData(
16465
+ CryptoUtils.packedUserOpTypedData(userOp, entryPointAddress, chainId),
16466
+ Number(chainId)
16467
+ );
16329
16468
  const signature = viem.concat([order.id, solverSignature]);
16330
16469
  return { ...userOp, signature };
16331
16470
  }
@@ -17250,15 +17389,67 @@ var UnsupportedIntentQuoteStrategyError = class extends Error {
17250
17389
  var UnsupportedIntentQuotePairError = class extends Error {
17251
17390
  constructor(params) {
17252
17391
  super(
17253
- `No Uniswap v4 pool config found for ${params.tokenIn.symbol ?? params.tokenIn.address} -> ${params.tokenOut.symbol ?? params.tokenOut.address} on ${params.source} -> ${params.destination}`
17392
+ `No ${params.quoteSource ?? "Uniswap v4 pool config"} found for ${params.tokenIn} -> ${params.tokenOut} on ${params.source} -> ${params.destination}`
17254
17393
  );
17255
17394
  this.name = "UnsupportedIntentQuotePairError";
17256
17395
  }
17257
17396
  };
17397
+ var PhantomSnapshotUnavailableError = class extends Error {
17398
+ constructor(tokenA, tokenB) {
17399
+ super(`No Phantom order price snapshot found for ${tokenA} -> ${tokenB}`);
17400
+ this.name = "PhantomSnapshotUnavailableError";
17401
+ }
17402
+ };
17403
+ var InvalidPhantomSnapshotError = class extends Error {
17404
+ constructor(commitment, reason) {
17405
+ super(`Invalid Phantom order price snapshot ${commitment}: ${reason}`);
17406
+ this.name = "InvalidPhantomSnapshotError";
17407
+ }
17408
+ };
17409
+ var BPS_DENOMINATOR = 10000n;
17410
+ function validateQuoteParams(params) {
17411
+ const hasAmountIn = params.amountIn !== void 0;
17412
+ const hasAmountOut = params.amountOut !== void 0;
17413
+ if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
17414
+ if (params.amountIn !== void 0 && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
17415
+ if (params.amountOut !== void 0 && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
17416
+ if (params.tokenIn.toLowerCase() === params.tokenOut.toLowerCase()) {
17417
+ throw new Error("tokenIn and tokenOut cannot be the same");
17418
+ }
17419
+ }
17420
+ async function readProtocolFeeBps(chainConfigService, source) {
17421
+ const gatewayAddress = chainConfigService.getIntentGatewayAddress(source.stateMachineId);
17422
+ if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === viem.zeroAddress) {
17423
+ throw new Error(`IntentGatewayV2 is not configured for chain ${source.stateMachineId}`);
17424
+ }
17425
+ const gatewayParams = await source.client.readContract({
17426
+ address: gatewayAddress,
17427
+ abi: IntentGatewayV2_default.ABI,
17428
+ functionName: "params"
17429
+ });
17430
+ const protocolFeeBps = Array.isArray(gatewayParams) ? BigInt(gatewayParams[4]) : BigInt(gatewayParams.protocolFeeBps ?? 0);
17431
+ if (protocolFeeBps < 0n || protocolFeeBps >= BPS_DENOMINATOR) {
17432
+ throw new Error(`Invalid IntentGateway protocol fee: ${protocolFeeBps} bps`);
17433
+ }
17434
+ return protocolFeeBps;
17435
+ }
17436
+ function deductProtocolFee(amount, protocolFeeBps) {
17437
+ if (protocolFeeBps <= 0n) return amount;
17438
+ const fee = amount * protocolFeeBps / BPS_DENOMINATOR;
17439
+ return amount - fee;
17440
+ }
17441
+ function grossUpForProtocolFee(netAmount, protocolFeeBps) {
17442
+ if (protocolFeeBps <= 0n) return netAmount;
17443
+ if (protocolFeeBps >= BPS_DENOMINATOR) throw new Error("protocolFeeBps must be less than 10,000");
17444
+ return divCeil(netAmount * BPS_DENOMINATOR, BPS_DENOMINATOR - protocolFeeBps);
17445
+ }
17446
+ function divCeil(numerator, denominator) {
17447
+ if (denominator <= 0n) throw new Error("denominator must be greater than zero");
17448
+ return (numerator + denominator - 1n) / denominator;
17449
+ }
17258
17450
 
17259
17451
  // src/protocols/intents/quote/uniswapV4.ts
17260
17452
  var UNISWAP_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
17261
- var BPS_DENOMINATOR = 10000n;
17262
17453
  var UniswapV4IntentQuoteStrategy = class {
17263
17454
  constructor(chainConfigService) {
17264
17455
  this.chainConfigService = chainConfigService;
@@ -17266,10 +17457,10 @@ var UniswapV4IntentQuoteStrategy = class {
17266
17457
  chainConfigService;
17267
17458
  baseQuoteClient;
17268
17459
  async quote(params, source, destination) {
17269
- this.validateQuoteParams(params);
17270
- const protocolFeeBps = await this.readProtocolFeeBps(source.client, source.stateMachineId);
17460
+ validateQuoteParams(params);
17461
+ const protocolFeeBps = await readProtocolFeeBps(this.chainConfigService, source);
17271
17462
  const quoteClient = this.resolveQuoteClient(source, destination);
17272
- const poolConfig = this.resolvePoolConfig(params, source.stateMachineId, UNISWAP_INTENT_QUOTE_CHAIN);
17463
+ const poolConfig = this.resolvePoolConfig(params, source.stateMachineId, destination.stateMachineId);
17273
17464
  return params.amountIn !== void 0 ? this.quoteExactInput({ params, client: quoteClient, protocolFeeBps, poolConfig }) : this.quoteExactOutput({ params, client: quoteClient, protocolFeeBps, poolConfig });
17274
17465
  }
17275
17466
  resolveQuoteClient(source, destination) {
@@ -17285,34 +17476,11 @@ var UniswapV4IntentQuoteStrategy = class {
17285
17476
  this.baseQuoteClient = baseQuoteClient;
17286
17477
  return baseQuoteClient;
17287
17478
  }
17288
- validateQuoteParams(params) {
17289
- const hasAmountIn = params.amountIn !== void 0;
17290
- const hasAmountOut = params.amountOut !== void 0;
17291
- if (hasAmountIn === hasAmountOut) throw new Error("Provide exactly one of amountIn or amountOut");
17292
- if (hasAmountIn && params.amountIn <= 0n) throw new Error("amountIn must be greater than zero");
17293
- if (hasAmountOut && params.amountOut <= 0n) throw new Error("amountOut must be greater than zero");
17294
- if (params.tokenIn.address.toLowerCase() === params.tokenOut.address.toLowerCase()) {
17295
- throw new Error("tokenIn and tokenOut cannot be the same");
17296
- }
17297
- }
17298
- async readProtocolFeeBps(client, chain) {
17299
- const gatewayAddress = this.chainConfigService.getIntentGatewayAddress(chain);
17300
- if (!gatewayAddress || gatewayAddress === "0x" || gatewayAddress === viem.zeroAddress) {
17301
- throw new Error(`IntentGatewayV2 is not configured for chain ${chain}`);
17302
- }
17303
- const gatewayParams = await client.readContract({
17304
- address: gatewayAddress,
17305
- abi: IntentGatewayV2_default.ABI,
17306
- functionName: "params"
17307
- });
17308
- if (isGatewayParamsTuple(gatewayParams)) return BigInt(gatewayParams[4]);
17309
- return BigInt(gatewayParams.protocolFeeBps ?? 0);
17310
- }
17311
17479
  resolvePoolConfig(params, source, destination) {
17312
17480
  const override = params.uniswapV4?.poolKey;
17313
17481
  if (override) {
17314
17482
  const poolKey = normalizePoolKey(override);
17315
- const tokenInForQuote = viem.getAddress(override.currencyIn ?? params.tokenIn.address);
17483
+ const tokenInForQuote = viem.getAddress(override.currencyIn ?? params.tokenIn);
17316
17484
  if (tokenInForQuote !== poolKey.currency0 && tokenInForQuote !== poolKey.currency1) {
17317
17485
  throw new Error(
17318
17486
  `Input currency ${tokenInForQuote} is not part of the override pool (${poolKey.currency0}, ${poolKey.currency1}). For cross-chain quotes pass uniswapV4.poolKey.currencyIn with the Base-side input currency address.`
@@ -17320,11 +17488,11 @@ var UniswapV4IntentQuoteStrategy = class {
17320
17488
  }
17321
17489
  return {
17322
17490
  poolKey,
17323
- quoterAddress: this.resolveQuoterAddress(destination, override.quoterAddress),
17491
+ quoterAddress: this.resolveQuoterAddress(UNISWAP_INTENT_QUOTE_CHAIN, override.quoterAddress),
17324
17492
  tokenInForQuote
17325
17493
  };
17326
17494
  }
17327
- const poolConfig = this.resolveConfiguredPool(params, destination);
17495
+ const poolConfig = this.resolveConfiguredPool(params, source, destination, UNISWAP_INTENT_QUOTE_CHAIN);
17328
17496
  if (poolConfig) return poolConfig;
17329
17497
  throw new UnsupportedIntentQuotePairError({
17330
17498
  source,
@@ -17333,12 +17501,12 @@ var UniswapV4IntentQuoteStrategy = class {
17333
17501
  tokenOut: params.tokenOut
17334
17502
  });
17335
17503
  }
17336
- resolveConfiguredPool(params, chain) {
17337
- for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(chain)) {
17338
- const resolvedPool = this.resolveConfiguredPoolTokens(chain, pool);
17504
+ resolveConfiguredPool(params, sourceChain, destinationChain, quoteChain) {
17505
+ for (const pool of this.chainConfigService.getUniswapV4PoolConfigs(quoteChain)) {
17506
+ const resolvedPool = this.resolveConfiguredPoolTokens(quoteChain, pool);
17339
17507
  if (!resolvedPool) continue;
17340
- const tokenInForQuote = matchPoolToken(params.tokenIn, resolvedPool);
17341
- const tokenOutForQuote = matchPoolToken(params.tokenOut, resolvedPool);
17508
+ const tokenInForQuote = this.matchPoolToken(params.tokenIn, sourceChain, resolvedPool);
17509
+ const tokenOutForQuote = this.matchPoolToken(params.tokenOut, destinationChain, resolvedPool);
17342
17510
  if (!tokenInForQuote || !tokenOutForQuote || tokenInForQuote.symbol === tokenOutForQuote.symbol) continue;
17343
17511
  const { currency0, currency1 } = sortCurrencies(resolvedPool[0].address, resolvedPool[1].address);
17344
17512
  return {
@@ -17349,7 +17517,7 @@ var UniswapV4IntentQuoteStrategy = class {
17349
17517
  tickSpacing: pool.tickSpacing,
17350
17518
  hooks: viem.getAddress(pool.hooks ?? viem.zeroAddress)
17351
17519
  },
17352
- quoterAddress: this.resolveQuoterAddress(chain),
17520
+ quoterAddress: this.resolveQuoterAddress(quoteChain),
17353
17521
  tokenInForQuote: tokenInForQuote.address
17354
17522
  };
17355
17523
  }
@@ -17372,8 +17540,18 @@ var UniswapV4IntentQuoteStrategy = class {
17372
17540
  if (!address || address === "0x") return null;
17373
17541
  return { symbol, address: viem.getAddress(address) };
17374
17542
  }
17543
+ matchPoolToken(tokenAddress, orderChain, poolTokens) {
17544
+ const addressMatch = poolTokens.find(
17545
+ (poolToken) => poolToken.address.toLowerCase() === tokenAddress.toLowerCase()
17546
+ );
17547
+ if (addressMatch) return addressMatch;
17548
+ const metadata = this.chainConfigService.getAssetMetadataByAddress(orderChain, tokenAddress);
17549
+ if (!metadata) return null;
17550
+ return poolTokens.find((poolToken) => poolToken.symbol === metadata.symbol) ?? null;
17551
+ }
17375
17552
  async quoteExactInput(args) {
17376
17553
  const amountIn = args.params.amountIn;
17554
+ if (amountIn === void 0) throw new Error("amountIn is required for an exact-input quote");
17377
17555
  const swapAmountIn = deductProtocolFee(amountIn, args.protocolFeeBps);
17378
17556
  const amountOut = await this.readV4QuoteExactInput(args.client, args.poolConfig, swapAmountIn);
17379
17557
  return {
@@ -17391,6 +17569,7 @@ var UniswapV4IntentQuoteStrategy = class {
17391
17569
  }
17392
17570
  async quoteExactOutput(args) {
17393
17571
  const amountOut = args.params.amountOut;
17572
+ if (amountOut === void 0) throw new Error("amountOut is required for an exact-output quote");
17394
17573
  const swapAmountIn = await this.readV4QuoteExactOutput(args.client, args.poolConfig, amountOut);
17395
17574
  const amountIn = grossUpForProtocolFee(swapAmountIn, args.protocolFeeBps);
17396
17575
  return {
@@ -17469,34 +17648,125 @@ function sortCurrencies(tokenIn, tokenOut) {
17469
17648
  const output = viem.getAddress(tokenOut);
17470
17649
  return BigInt(input) < BigInt(output) ? { currency0: input, currency1: output } : { currency0: output, currency1: input };
17471
17650
  }
17472
- function matchPoolToken(token, poolTokens) {
17473
- const tokenAddress = token.address.toLowerCase();
17474
- const addressMatch = poolTokens.find((poolToken) => poolToken.address.toLowerCase() === tokenAddress);
17475
- if (addressMatch) return addressMatch;
17476
- const tokenSymbol = token.symbol?.toUpperCase();
17477
- if (!tokenSymbol) return null;
17478
- return poolTokens.find((poolToken) => poolToken.symbol.toUpperCase() === tokenSymbol) ?? null;
17479
- }
17480
17651
  function getZeroForOne(tokenIn, poolKey) {
17481
17652
  return viem.getAddress(tokenIn).toLowerCase() === viem.getAddress(poolKey.currency0).toLowerCase();
17482
17653
  }
17483
- function isGatewayParamsTuple(value) {
17484
- return Array.isArray(value);
17485
- }
17486
- function deductProtocolFee(amount, protocolFeeBps) {
17487
- if (protocolFeeBps <= 0n) return amount;
17488
- const fee = amount * protocolFeeBps / BPS_DENOMINATOR;
17489
- return amount - fee;
17490
- }
17491
- function grossUpForProtocolFee(netAmount, protocolFeeBps) {
17492
- if (protocolFeeBps <= 0n) return netAmount;
17493
- return divCeil(netAmount * BPS_DENOMINATOR, BPS_DENOMINATOR - protocolFeeBps);
17654
+
17655
+ // src/protocols/intents/quote/phantomSnapshot.ts
17656
+ var PHANTOM_INTENT_QUOTE_CHAIN = "EVM-8453" /* BASE_MAINNET */;
17657
+ var BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET = {
17658
+ USDC: "USDC",
17659
+ USDT: "USDC",
17660
+ cNGN: "cNGN"
17661
+ };
17662
+ var SUPPORTED_BASE_SNAPSHOT_PAIRS = /* @__PURE__ */ new Set(["USDC:cNGN", "cNGN:USDC"]);
17663
+ var PhantomSnapshotIntentQuoteStrategy = class {
17664
+ constructor(chainConfigService, getQueryClient) {
17665
+ this.chainConfigService = chainConfigService;
17666
+ this.getQueryClient = getQueryClient;
17667
+ }
17668
+ chainConfigService;
17669
+ getQueryClient;
17670
+ async quote(params, source, destination) {
17671
+ validateQuoteParams(params);
17672
+ const pair = this.resolveBaseSnapshotPair(params, source.stateMachineId, destination.stateMachineId);
17673
+ if (!pair) {
17674
+ throw new UnsupportedIntentQuotePairError({
17675
+ source: source.stateMachineId,
17676
+ destination: destination.stateMachineId,
17677
+ tokenIn: params.tokenIn,
17678
+ tokenOut: params.tokenOut,
17679
+ quoteSource: "Phantom snapshot pair"
17680
+ });
17681
+ }
17682
+ const queryClient = this.getQueryClient();
17683
+ const [protocolFeeBps, snapshot] = await Promise.all([
17684
+ readProtocolFeeBps(this.chainConfigService, source),
17685
+ _queryLatestPhantomOrderPriceSnapshot({
17686
+ tokenA: pair.tokenA,
17687
+ tokenB: pair.tokenB,
17688
+ queryClient
17689
+ })
17690
+ ]);
17691
+ if (!snapshot) throw new PhantomSnapshotUnavailableError(pair.tokenA, pair.tokenB);
17692
+ this.validateSnapshot(snapshot);
17693
+ return this.quoteSnapshot(params, protocolFeeBps, snapshot);
17694
+ }
17695
+ quoteSnapshot(params, protocolFeeBps, snapshot) {
17696
+ if (params.amountIn !== void 0) {
17697
+ const netAmountIn2 = deductProtocolFee(params.amountIn, protocolFeeBps);
17698
+ const amountOut = netAmountIn2 * snapshot.medianPrice / snapshot.standardAmount;
17699
+ if (amountOut <= 0n) {
17700
+ throw new InvalidPhantomSnapshotError(snapshot.commitment, "quote rounds down to zero output");
17701
+ }
17702
+ return this.buildResult("EXACT_INPUT", params.amountIn, amountOut, protocolFeeBps, snapshot);
17703
+ }
17704
+ if (params.amountOut === void 0) throw new Error("Quote amount is missing after validation");
17705
+ const netAmountIn = divCeil(params.amountOut * snapshot.standardAmount, snapshot.medianPrice);
17706
+ const amountIn = grossUpForProtocolFee(netAmountIn, protocolFeeBps);
17707
+ return this.buildResult("EXACT_OUTPUT", amountIn, params.amountOut, protocolFeeBps, snapshot);
17708
+ }
17709
+ buildResult(tradeType, amountIn, amountOut, protocolFeeBps, snapshot) {
17710
+ return {
17711
+ strategy: "phantom_snapshot",
17712
+ tradeType,
17713
+ amountIn,
17714
+ amountOut,
17715
+ quoteMetadata: {
17716
+ quoteChain: PHANTOM_INTENT_QUOTE_CHAIN,
17717
+ commitment: snapshot.commitment,
17718
+ tokenA: snapshot.tokenA,
17719
+ tokenB: snapshot.tokenB,
17720
+ standardAmount: snapshot.standardAmount,
17721
+ medianPrice: snapshot.medianPrice,
17722
+ lowestPrice: snapshot.lowestPrice,
17723
+ highestPrice: snapshot.highestPrice,
17724
+ blockNumber: snapshot.blockNumber,
17725
+ snapshotTime: snapshot.snapshotTime,
17726
+ bidCount: snapshot.bidCount,
17727
+ protocolFeeBps
17728
+ }
17729
+ };
17730
+ }
17731
+ validateSnapshot(snapshot) {
17732
+ if (snapshot.standardAmount <= 0n) {
17733
+ throw new InvalidPhantomSnapshotError(snapshot.commitment, "standardAmount must be greater than zero");
17734
+ }
17735
+ if (snapshot.medianPrice <= 0n) {
17736
+ throw new InvalidPhantomSnapshotError(snapshot.commitment, "medianPrice must be greater than zero");
17737
+ }
17738
+ if (snapshot.bidCount <= 0) {
17739
+ throw new InvalidPhantomSnapshotError(snapshot.commitment, "bidCount must be greater than zero");
17740
+ }
17741
+ if (Number.isNaN(snapshot.snapshotTime.getTime())) {
17742
+ throw new InvalidPhantomSnapshotError(snapshot.commitment, "snapshotTime is invalid");
17743
+ }
17744
+ }
17745
+ resolveBaseSnapshotPair(params, sourceStateMachineId, destinationStateMachineId) {
17746
+ const tokenIn = this.resolveBaseSnapshotToken(sourceStateMachineId, params.tokenIn);
17747
+ const tokenOut = this.resolveBaseSnapshotToken(destinationStateMachineId, params.tokenOut);
17748
+ if (!tokenIn || !tokenOut || !isSupportedSnapshotPair(tokenIn.symbol, tokenOut.symbol)) return;
17749
+ return { tokenA: tokenIn.address, tokenB: tokenOut.address };
17750
+ }
17751
+ resolveBaseSnapshotToken(chain, tokenAddress) {
17752
+ const orderAsset = this.chainConfigService.getAssetMetadataByAddress(chain, tokenAddress)?.symbol;
17753
+ if (!orderAsset) return;
17754
+ const snapshotAsset = BASE_SNAPSHOT_ASSET_BY_ORDER_ASSET[orderAsset];
17755
+ if (!snapshotAsset) return;
17756
+ const address = this.chainConfigService.getAssetAddress(PHANTOM_INTENT_QUOTE_CHAIN, snapshotAsset);
17757
+ if (!isConfiguredAddress(address)) return;
17758
+ return { symbol: snapshotAsset, address };
17759
+ }
17760
+ };
17761
+ function isSupportedSnapshotPair(tokenA, tokenB) {
17762
+ return SUPPORTED_BASE_SNAPSHOT_PAIRS.has(`${tokenA}:${tokenB}`);
17494
17763
  }
17495
- function divCeil(numerator, denominator) {
17496
- return (numerator + denominator - 1n) / denominator;
17764
+ function isConfiguredAddress(address) {
17765
+ return Boolean(address && address !== "0x" && !/^0x0{40}$/i.test(address));
17497
17766
  }
17498
17767
 
17499
17768
  // src/protocols/intents/IntentGateway.ts
17769
+ var CROSS_CHAIN_ORDER_FEE_GAS_BUMP = 600000n;
17500
17770
  var IntentGateway = class _IntentGateway {
17501
17771
  /** EVM chain on which orders are placed and escrowed. */
17502
17772
  source;
@@ -17568,6 +17838,10 @@ var IntentGateway = class _IntentGateway {
17568
17838
  this.gasEstimator = gasEstimator;
17569
17839
  this._crypto = crypto;
17570
17840
  this.quoteStrategies = {
17841
+ phantom_snapshot: new PhantomSnapshotIntentQuoteStrategy(
17842
+ dest.configService,
17843
+ () => this.requireIndexer().queryClient
17844
+ ),
17571
17845
  uniswap_v4: new UniswapV4IntentQuoteStrategy(dest.configService)
17572
17846
  };
17573
17847
  }
@@ -17617,37 +17891,39 @@ var IntentGateway = class _IntentGateway {
17617
17891
  /**
17618
17892
  * Quotes an intent between this gateway's source and destination chains.
17619
17893
  *
17620
- * `strategy` defaults to `uniswap_v4`, currently the only supported
17621
- * strategy. Provide exactly one of `amountIn` or `amountOut`.
17894
+ * Uses the latest directional Phantom order price snapshot from the attached
17895
+ * indexer by default. Pass `strategy: "uniswap_v4"` only when explicitly
17896
+ * requesting a Uniswap quote. Provide exactly one of `amountIn` or `amountOut`.
17622
17897
  *
17623
- * The Uniswap quote strategy always prices against the configured Base
17624
- * pool, regardless of this gateway's destination chain. Returned
17898
+ * Both built-in strategies resolve their canonical market on Base,
17899
+ * regardless of this gateway's destination chain. Returned
17625
17900
  * `amountIn`/`amountOut` already account for the gateway's protocol fee
17626
17901
  * (`quoteMetadata.protocolFeeBps`), which the gateway deducts from order
17627
- * inputs; apply only your own slippage tolerance before placing the order.
17902
+ * inputs; use the returned amounts directly when placing the order.
17628
17903
  *
17629
17904
  * @param params - Token pair, amount, and optional strategy/pool overrides.
17630
17905
  * @returns The quoted amounts plus strategy-specific metadata.
17631
17906
  * @throws {UnsupportedIntentQuoteStrategyError} For unknown strategies.
17632
- * @throws {UnsupportedIntentQuotePairError} When no pool is configured for the pair.
17907
+ * @throws {UnsupportedIntentQuotePairError} When the selected strategy does not support the pair.
17908
+ * @throws {PhantomSnapshotUnavailableError} When an eligible cNGN pair has no snapshot.
17633
17909
  */
17634
17910
  async quoteIntent(params) {
17635
- const strategy = params.strategy ?? "uniswap_v4";
17911
+ const source = { stateMachineId: this.source.config.stateMachineId, client: this.source.client };
17912
+ const destination = { stateMachineId: this.dest.config.stateMachineId, client: this.dest.client };
17913
+ const strategy = params.strategy ?? "phantom_snapshot";
17636
17914
  const handler = this.quoteStrategies[strategy];
17637
17915
  if (!handler) throw new UnsupportedIntentQuoteStrategyError(strategy);
17638
- return handler.quote(
17639
- { ...params, strategy },
17640
- { stateMachineId: this.source.config.stateMachineId, client: this.source.client },
17641
- { stateMachineId: this.dest.config.stateMachineId, client: this.dest.client }
17642
- );
17916
+ return handler.quote({ ...params, strategy }, source, destination);
17643
17917
  }
17644
17918
  /**
17645
17919
  * Bidirectional async generator that orchestrates the full order lifecycle:
17646
17920
  * placement, fee estimation, bid collection, and execution.
17647
17921
  *
17648
17922
  * **Yield/receive protocol:**
17649
- * 1. If `order.fees` is unset or zero, estimates gas and sets `order.fees`
17650
- * with a 1% buffer and the wei cost with a 2% buffer for the `value` field.
17923
+ * 1. If `order.fees` is unset or zero, estimates gas and sets same-chain
17924
+ * `order.fees` to twice the estimate. Cross-chain orders retain a 1% buffer
17925
+ * and include an additional 600k-gas fee uplift, while the wei cost used for
17926
+ * the `value` field receives a 2% buffer.
17651
17927
  * 2. Yields `AWAITING_PLACE_ORDER` with `{ to, data, value, sessionPrivateKey }`.
17652
17928
  * The caller must sign the transaction and pass it back via `gen.next(signedTx)`.
17653
17929
  * 3. Yields `ORDER_PLACED` with the finalised order and transaction hash once
@@ -17679,8 +17955,15 @@ var IntentGateway = class _IntentGateway {
17679
17955
  if (estimate.totalGasCostWei === 0n || estimate.totalGasInFeeToken === 0n) {
17680
17956
  throw new Error("Gas estimation failed");
17681
17957
  }
17958
+ const isSameChain = this.source.config.stateMachineId === this.dest.config.stateMachineId;
17682
17959
  value = estimate.totalGasCostWei + estimate.totalGasCostWei * 2n / 100n;
17683
- order.fees = estimate.totalGasInFeeToken + estimate.totalGasInFeeToken * 1n / 100n;
17960
+ const crossChainFeeBump = isSameChain ? 0n : await convertGasToFeeToken(
17961
+ this.ctx,
17962
+ CROSS_CHAIN_ORDER_FEE_GAS_BUMP,
17963
+ "source",
17964
+ this.source.config.stateMachineId
17965
+ );
17966
+ order.fees = isSameChain ? estimate.totalGasInFeeToken * 2n : estimate.totalGasInFeeToken + (crossChainFeeBump + estimate.totalGasInFeeToken * 1n / 100n);
17684
17967
  }
17685
17968
  const placeOrderGen = this.orderPlacer.placeOrder(order, graffiti);
17686
17969
  const placeOrderFirst = await placeOrderGen.next();
@@ -18061,7 +18344,9 @@ var IntentGateway = class _IntentGateway {
18061
18344
  }
18062
18345
  requireIndexer() {
18063
18346
  if (!this.indexer) {
18064
- throw new Error("IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods");
18347
+ throw new Error(
18348
+ "IntentGateway: call withQueryClient(queryClient) before using indexer-backed methods or Phantom quotes"
18349
+ );
18065
18350
  }
18066
18351
  return this.indexer;
18067
18352
  }
@@ -22596,6 +22881,7 @@ exports.IntentGateway = IntentGateway;
22596
22881
  exports.IntentGatewayABI = ABI3;
22597
22882
  exports.IntentOrderStatus = IntentOrderStatus;
22598
22883
  exports.IntentsCoprocessor = IntentsCoprocessor;
22884
+ exports.InvalidPhantomSnapshotError = InvalidPhantomSnapshotError;
22599
22885
  exports.IsmpClient = IsmpClient;
22600
22886
  exports.MOCK_ADDRESS = MOCK_ADDRESS;
22601
22887
  exports.ORDER_V2_PARAM_TYPE = ORDER_V2_PARAM_TYPE;
@@ -22603,6 +22889,7 @@ exports.OrderStatus = OrderStatus;
22603
22889
  exports.OrderStatusChecker = OrderStatusChecker;
22604
22890
  exports.PACKED_USEROP_TYPEHASH = PACKED_USEROP_TYPEHASH;
22605
22891
  exports.PLACE_ORDER_SELECTOR = PLACE_ORDER_SELECTOR;
22892
+ exports.PhantomSnapshotUnavailableError = PhantomSnapshotUnavailableError;
22606
22893
  exports.PharosChain = PharosChain;
22607
22894
  exports.PolkadotHubChain = PolkadotHubChain;
22608
22895
  exports.REQUEST_COMMITMENTS_SLOT = REQUEST_COMMITMENTS_SLOT;