@hyperbridge/sdk 1.3.5 → 1.3.6

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.
@@ -2024,7 +2024,7 @@ declare function encodeISMPMessage(message: IIsmpMessage): Uint8Array;
2024
2024
  /**
2025
2025
  * Type representing an ISMP message.
2026
2026
  */
2027
- type IIsmpMessage = IRequestMessage | ITimeoutPostRequestMessage | IGetResponseMessage;
2027
+ type IIsmpMessage = IRequestMessage | ITimeoutPostRequestMessage | IGetResponseMessage | IGetRequestMessage;
2028
2028
  interface IRequestMessage {
2029
2029
  /**
2030
2030
  * The kind of message.
@@ -2053,9 +2053,13 @@ interface IGetRequestMessage {
2053
2053
  */
2054
2054
  requests: IGetRequest[];
2055
2055
  /**
2056
- * The proof of the requests.
2056
+ * The proof of the requests from the source chain.
2057
2057
  */
2058
- proof: IProof;
2058
+ source: IProof;
2059
+ /**
2060
+ * The proof of the response from the target chain
2061
+ */
2062
+ response: IProof;
2059
2063
  /**
2060
2064
  * The signer of the message.
2061
2065
  */
@@ -2593,8 +2597,7 @@ declare class IntentGateway {
2593
2597
  * Uses USD pricing to convert between fee token amounts and native token costs.
2594
2598
  *
2595
2599
  * @param feeTokenAmount - The amount in fee token (DAI)
2596
- * @param publicClient - The client for the chain to get native token info
2597
- * @param feeTokenDecimals - The decimal places of the fee token
2600
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the conversion
2598
2601
  * @returns The fee token amount converted to native token amount
2599
2602
  * @private
2600
2603
  */
@@ -2604,18 +2607,24 @@ declare class IntentGateway {
2604
2607
  * Uses USD pricing to convert between native token gas costs and fee token amounts.
2605
2608
  *
2606
2609
  * @param gasEstimate - The estimated gas units
2607
- * @param publicClient - The client for the chain to get gas prices
2608
- * @param targetDecimals - The decimal places of the target fee token
2610
+ * @param gasEstimateIn - Whether to use "source" or "dest" chain for the conversion
2609
2611
  * @returns The gas cost converted to fee token amount
2610
2612
  * @private
2611
2613
  */
2612
2614
  private convertGasToFeeToken;
2615
+ /**
2616
+ * Gets a quote for the native token cost of dispatching a post request.
2617
+ *
2618
+ * @param postRequest - The post request to quote
2619
+ * @param fee - The fee amount in fee token
2620
+ * @returns The native token amount required
2621
+ */
2613
2622
  quoteNative(postRequest: IPostRequest, fee: bigint): Promise<bigint>;
2614
2623
  /**
2615
2624
  * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given a desired output amount.
2616
2625
  * Compares liquidity and pricing across different protocols and fee tiers.
2617
2626
  *
2618
- * @param chain - The chain identifier where the swap will occur
2627
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the swap
2619
2628
  * @param tokenIn - The address of the input token
2620
2629
  * @param tokenOut - The address of the output token
2621
2630
  * @param amountOut - The desired output amount
@@ -2630,10 +2639,11 @@ declare class IntentGateway {
2630
2639
  * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given an input amount.
2631
2640
  * Compares liquidity and pricing across different protocols and fee tiers.
2632
2641
  *
2633
- * @param chain - The chain identifier where the swap will occur
2642
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the swap
2634
2643
  * @param tokenIn - The address of the input token
2635
2644
  * @param tokenOut - The address of the output token
2636
2645
  * @param amountIn - The input amount to swap
2646
+ * @param selectedProtocol - Optional specific protocol to use ("v2", "v3", or "v4")
2637
2647
  * @returns Object containing the best protocol, expected output amount, and fee tier (for V3/V4)
2638
2648
  */
2639
2649
  findBestProtocolWithAmountIn(getQuoteIn: "source" | "dest", tokenIn: HexString, tokenOut: HexString, amountIn: bigint, selectedProtocol?: "v2" | "v3" | "v4"): Promise<{
@@ -3,7 +3,7 @@ import { join } from 'path';
3
3
  import { TextDecoder as TextDecoder$1, TextEncoder as TextEncoder$1 } from 'util';
4
4
  import { createConsola, LogLevels } from 'consola';
5
5
  import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
6
- import { toHex, hexToBytes, encodePacked, keccak256, encodeAbiParameters, bytesToHex, concatHex, createPublicClient, http, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, maxUint256, parseUnits } from 'viem';
6
+ import { toHex, hexToBytes, encodePacked, keccak256, encodeAbiParameters, bytesToHex, concatHex, createPublicClient, http, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, maxUint256, formatUnits, parseUnits } from 'viem';
7
7
  import mergeRace from '@async-generator/merge-race';
8
8
  import { gnosisChiado, gnosis, bscTestnet, bsc, soneium, baseSepolia, base, optimismSepolia, optimism, arbitrumSepolia, arbitrum, mainnet, sepolia } from 'viem/chains';
9
9
  import { hasWindow, isNode, env } from 'std-env';
@@ -13,6 +13,7 @@ import { WsProvider, ApiPromise } from '@polkadot/api';
13
13
  import { RpcWebSocketClient } from 'rpc-websocket-client';
14
14
  import { keccakAsU8a, decodeAddress, xxhashAsU8a } from '@polkadot/util-crypto';
15
15
  import { GraphQLClient } from 'graphql-request';
16
+ import { Decimal } from 'decimal.js';
16
17
  import { u8aToHex } from '@polkadot/util';
17
18
 
18
19
  var __defProp = Object.defineProperty;
@@ -3933,6 +3934,10 @@ var GetRequest = Struct({
3933
3934
  * Substrate Keys
3934
3935
  */
3935
3936
  keys: Vector(Vector(u8)),
3937
+ /*
3938
+ * The height of the state machine
3939
+ */
3940
+ height: u64,
3936
3941
  /*
3937
3942
  * Some application-specific metadata relating to this request
3938
3943
  */
@@ -4059,6 +4064,24 @@ var TimeoutMessage = Enum({
4059
4064
  requests: Vector(Request)
4060
4065
  })
4061
4066
  });
4067
+ var GetRequestsWithProof = Struct({
4068
+ /*
4069
+ * Requests to be fetched
4070
+ */
4071
+ requests: Vector(GetRequest),
4072
+ /*
4073
+ * Membership batch proof for these requests
4074
+ */
4075
+ source: Proof,
4076
+ /*
4077
+ * Storage proof for these responses
4078
+ */
4079
+ response: Proof,
4080
+ /*
4081
+ * Signer information. Ideally should be their account identifier
4082
+ */
4083
+ signer: Vector(u8)
4084
+ });
4062
4085
  var Message = Enum({
4063
4086
  /*
4064
4087
  * A consensus update message
@@ -4807,6 +4830,8 @@ var EvmChain = class {
4807
4830
  ]
4808
4831
  });
4809
4832
  return encoded2;
4833
+ }).with({ kind: "GetRequest" }, (message2) => {
4834
+ throw new Error("GetResponse is not yet supported on Substrate chains");
4810
4835
  }).exhaustive();
4811
4836
  return encoded;
4812
4837
  }
@@ -5122,8 +5147,13 @@ var SubstrateChain = class {
5122
5147
  async submitUnsigned(message) {
5123
5148
  if (!this.api) throw new Error("API not initialized");
5124
5149
  const { api } = this;
5125
- const args = hexToBytes(this.encode(message)).slice(2);
5126
- const tx = api.tx.ismp.handleUnsigned(args);
5150
+ const args = encodeISMPMessage(message);
5151
+ let tx;
5152
+ if (message.kind === "GetRequest") {
5153
+ tx = api.tx.stateCoprocessor.handleUnsigned(args);
5154
+ } else {
5155
+ tx = api.tx.ismp.handleUnsigned(args);
5156
+ }
5127
5157
  return new Promise((resolve, reject) => {
5128
5158
  let unsub = () => {
5129
5159
  };
@@ -5266,6 +5296,18 @@ function convertIPostRequestToCodec(request) {
5266
5296
  }
5267
5297
  };
5268
5298
  }
5299
+ function convertIGetRequestToCodec(request) {
5300
+ return {
5301
+ source: convertStateMachineIdToEnum(request.source),
5302
+ dest: convertStateMachineIdToEnum(request.dest),
5303
+ from: Array.from(hexToBytes(request.from)),
5304
+ nonce: request.nonce,
5305
+ keys: request.keys.map((key) => Array.from(hexToBytes(key))),
5306
+ context: Array.from(hexToBytes(request.context)),
5307
+ timeoutTimestamp: request.timeoutTimestamp,
5308
+ height: request.height
5309
+ };
5310
+ }
5269
5311
  function encodeISMPMessage(message) {
5270
5312
  try {
5271
5313
  return match(message).with({ kind: "PostRequest" }, (message2) => {
@@ -5292,6 +5334,31 @@ function encodeISMPMessage(message) {
5292
5334
  ]);
5293
5335
  }).with({ kind: "GetResponse" }, (message2) => {
5294
5336
  throw new Error("GetResponse is not yet supported on Substrate chains");
5337
+ }).with({ kind: "GetRequest" }, (message2) => {
5338
+ return GetRequestsWithProof.enc({
5339
+ requests: message2.requests.map((request) => convertIGetRequestToCodec(request)),
5340
+ source: {
5341
+ height: {
5342
+ height: message2.source.height,
5343
+ id: {
5344
+ consensusStateId: Array.from(toBytes(message2.source.consensusStateId)),
5345
+ id: convertStateMachineIdToEnum(message2.source.stateMachine)
5346
+ }
5347
+ },
5348
+ proof: Array.from(hexToBytes(message2.source.proof))
5349
+ },
5350
+ response: {
5351
+ height: {
5352
+ height: message2.response.height,
5353
+ id: {
5354
+ consensusStateId: Array.from(toBytes(message2.response.consensusStateId)),
5355
+ id: convertStateMachineIdToEnum(message2.response.stateMachine)
5356
+ }
5357
+ },
5358
+ proof: Array.from(hexToBytes(message2.response.proof))
5359
+ },
5360
+ signer: Array.from(hexToBytes(message2.signer))
5361
+ });
5295
5362
  }).with({ kind: "TimeoutPostRequest" }, (message2) => {
5296
5363
  return Vector(Message).enc([
5297
5364
  {
@@ -11488,8 +11555,6 @@ var UNISWAP_V4_QUOTER_ABI = [
11488
11555
  inputs: [{ name: "revertData", type: "bytes", internalType: "bytes" }]
11489
11556
  }
11490
11557
  ];
11491
-
11492
- // src/protocols/intents.ts
11493
11558
  var IntentGateway = class {
11494
11559
  /**
11495
11560
  * Creates a new IntentGateway instance for cross-chain operations.
@@ -11575,6 +11640,7 @@ var IntentGateway = class {
11575
11640
  }))
11576
11641
  ];
11577
11642
  let destChainFillGas = 0n;
11643
+ let filledWithNativeToken = false;
11578
11644
  try {
11579
11645
  let protocolFeeInNativeToken = await this.quoteNative(postRequest, relayerFeeInDestFeeToken);
11580
11646
  protocolFeeInNativeToken = protocolFeeInNativeToken + protocolFeeInNativeToken * 50n / 10000n;
@@ -11587,6 +11653,7 @@ var IntentGateway = class {
11587
11653
  value: totalEthValue + protocolFeeInNativeToken,
11588
11654
  stateOverride: stateOverrides
11589
11655
  });
11656
+ filledWithNativeToken = true;
11590
11657
  } catch {
11591
11658
  console.warn(
11592
11659
  `Could not estimate gas for fill order with native token as fees for chain ${order.destChain}, now trying with fee token as fees`
@@ -11628,18 +11695,18 @@ var IntentGateway = class {
11628
11695
  sourceChainFeeTokenDecimals
11629
11696
  );
11630
11697
  const protocolFeeInSourceFeeToken = adjustFeeDecimals(
11631
- // Following baseIsmpModule.sol, the protocol fee is added to the relayer fee
11632
- await this.dest.quote(postRequest) + relayerFeeInDestFeeToken,
11698
+ await this.dest.quote(postRequest),
11633
11699
  destChainFeeTokenDecimals,
11634
11700
  sourceChainFeeTokenDecimals
11635
11701
  );
11636
- const totalEstimate = fillGasInSourceFeeToken + protocolFeeInSourceFeeToken + relayerFeeInSourceFeeToken;
11637
- const SWAP_OPERATIONS_BPS = 3500n;
11638
- const swapOperationsInFeeToken = totalEstimate * SWAP_OPERATIONS_BPS / 10000n;
11639
- const totalFeeTokenAmount = totalEstimate + swapOperationsInFeeToken;
11640
- const totalNativeTokenAmount = await this.convertFeeTokenToNative(totalFeeTokenAmount, "source");
11702
+ let totalEstimateInSourceFeeToken = fillGasInSourceFeeToken + protocolFeeInSourceFeeToken + relayerFeeInSourceFeeToken;
11703
+ if (!filledWithNativeToken) {
11704
+ totalEstimateInSourceFeeToken = totalEstimateInSourceFeeToken + totalEstimateInSourceFeeToken * 200n / 10000n;
11705
+ }
11706
+ let totalNativeTokenAmount = await this.convertFeeTokenToNative(totalEstimateInSourceFeeToken, "source");
11707
+ totalNativeTokenAmount = totalNativeTokenAmount + totalNativeTokenAmount * 200n / 10000n;
11641
11708
  return {
11642
- feeTokenAmount: totalFeeTokenAmount,
11709
+ feeTokenAmount: totalEstimateInSourceFeeToken,
11643
11710
  nativeTokenAmount: totalNativeTokenAmount,
11644
11711
  postRequestCalldata
11645
11712
  };
@@ -11649,8 +11716,7 @@ var IntentGateway = class {
11649
11716
  * Uses USD pricing to convert between fee token amounts and native token costs.
11650
11717
  *
11651
11718
  * @param feeTokenAmount - The amount in fee token (DAI)
11652
- * @param publicClient - The client for the chain to get native token info
11653
- * @param feeTokenDecimals - The decimal places of the fee token
11719
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the conversion
11654
11720
  * @returns The fee token amount converted to native token amount
11655
11721
  * @private
11656
11722
  */
@@ -11659,22 +11725,33 @@ var IntentGateway = class {
11659
11725
  const evmChainID = `EVM-${client.chain?.id}`;
11660
11726
  const wethAsset = this[getQuoteIn].config.getWrappedNativeAssetWithDecimals(evmChainID).asset;
11661
11727
  const feeToken = await this[getQuoteIn].getFeeTokenWithDecimals();
11662
- const { amountOut } = await this.findBestProtocolWithAmountIn(
11663
- getQuoteIn,
11664
- feeToken.address,
11665
- wethAsset,
11666
- feeTokenAmount,
11667
- "v2"
11668
- );
11669
- return amountOut;
11728
+ try {
11729
+ const { amountOut } = await this.findBestProtocolWithAmountIn(
11730
+ getQuoteIn,
11731
+ feeToken.address,
11732
+ wethAsset,
11733
+ feeTokenAmount,
11734
+ "v2"
11735
+ );
11736
+ if (amountOut === 0n) {
11737
+ throw new Error();
11738
+ }
11739
+ return amountOut;
11740
+ } catch {
11741
+ const nativeCurrency = client.chain?.nativeCurrency;
11742
+ const chainId = client.chain?.id;
11743
+ const feeTokenAmountDecimal = new Decimal(formatUnits(feeTokenAmount, feeToken.decimals));
11744
+ const nativeTokenPriceUsd = new Decimal(await fetchPrice(nativeCurrency?.symbol, chainId));
11745
+ const totalCostInNativeToken = feeTokenAmountDecimal.dividedBy(nativeTokenPriceUsd);
11746
+ return parseUnits(totalCostInNativeToken.toFixed(nativeCurrency?.decimals), nativeCurrency?.decimals);
11747
+ }
11670
11748
  }
11671
11749
  /**
11672
11750
  * Converts gas costs to the equivalent amount in the fee token (DAI).
11673
11751
  * Uses USD pricing to convert between native token gas costs and fee token amounts.
11674
11752
  *
11675
11753
  * @param gasEstimate - The estimated gas units
11676
- * @param publicClient - The client for the chain to get gas prices
11677
- * @param targetDecimals - The decimal places of the target fee token
11754
+ * @param gasEstimateIn - Whether to use "source" or "dest" chain for the conversion
11678
11755
  * @returns The gas cost converted to fee token amount
11679
11756
  * @private
11680
11757
  */
@@ -11685,15 +11762,36 @@ var IntentGateway = class {
11685
11762
  const evmChainID = `EVM-${client.chain?.id}`;
11686
11763
  const wethAddr = this[gasEstimateIn].config.getWrappedNativeAssetWithDecimals(evmChainID).asset;
11687
11764
  const feeToken = await this[gasEstimateIn].getFeeTokenWithDecimals();
11688
- const { amountOut } = await this.findBestProtocolWithAmountIn(
11689
- gasEstimateIn,
11690
- wethAddr,
11691
- feeToken.address,
11692
- gasCostInWei,
11693
- "v2"
11694
- );
11695
- return amountOut;
11765
+ try {
11766
+ const { amountOut } = await this.findBestProtocolWithAmountIn(
11767
+ gasEstimateIn,
11768
+ wethAddr,
11769
+ feeToken.address,
11770
+ gasCostInWei,
11771
+ "v2"
11772
+ );
11773
+ if (amountOut === 0n) {
11774
+ throw new Error();
11775
+ }
11776
+ return amountOut;
11777
+ } catch {
11778
+ const nativeCurrency = client.chain?.nativeCurrency;
11779
+ const chainId = client.chain?.id;
11780
+ const gasCostInToken = new Decimal(formatUnits(gasCostInWei, nativeCurrency?.decimals));
11781
+ const tokenPriceUsd = await fetchPrice(nativeCurrency?.symbol, chainId);
11782
+ const gasCostUsd = gasCostInToken.times(tokenPriceUsd);
11783
+ const feeTokenPriceUsd = new Decimal(1);
11784
+ const gasCostInFeeToken = gasCostUsd.dividedBy(feeTokenPriceUsd);
11785
+ return parseUnits(gasCostInFeeToken.toFixed(feeToken.decimals), feeToken.decimals);
11786
+ }
11696
11787
  }
11788
+ /**
11789
+ * Gets a quote for the native token cost of dispatching a post request.
11790
+ *
11791
+ * @param postRequest - The post request to quote
11792
+ * @param fee - The fee amount in fee token
11793
+ * @returns The native token amount required
11794
+ */
11697
11795
  async quoteNative(postRequest, fee) {
11698
11796
  const dispatchPost = {
11699
11797
  dest: toHex(postRequest.dest),
@@ -11715,7 +11813,7 @@ var IntentGateway = class {
11715
11813
  * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given a desired output amount.
11716
11814
  * Compares liquidity and pricing across different protocols and fee tiers.
11717
11815
  *
11718
- * @param chain - The chain identifier where the swap will occur
11816
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the swap
11719
11817
  * @param tokenIn - The address of the input token
11720
11818
  * @param tokenOut - The address of the output token
11721
11819
  * @param amountOut - The desired output amount
@@ -11880,10 +11978,11 @@ var IntentGateway = class {
11880
11978
  * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given an input amount.
11881
11979
  * Compares liquidity and pricing across different protocols and fee tiers.
11882
11980
  *
11883
- * @param chain - The chain identifier where the swap will occur
11981
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the swap
11884
11982
  * @param tokenIn - The address of the input token
11885
11983
  * @param tokenOut - The address of the output token
11886
11984
  * @param amountIn - The input amount to swap
11985
+ * @param selectedProtocol - Optional specific protocol to use ("v2", "v3", or "v4")
11887
11986
  * @returns Object containing the best protocol, expected output amount, and fee tier (for V3/V4)
11888
11987
  */
11889
11988
  async findBestProtocolWithAmountIn(getQuoteIn, tokenIn, tokenOut, amountIn, selectedProtocol) {