@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<{
@@ -1,6 +1,6 @@
1
1
  import { createConsola, LogLevels } from 'consola';
2
2
  import { flatten, zip, capitalize, maxBy, isNil } from 'lodash-es';
3
- import { toHex, hexToBytes, encodePacked, keccak256, encodeAbiParameters, bytesToHex, concatHex, createPublicClient, http, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, maxUint256, parseUnits } from 'viem';
3
+ import { toHex, hexToBytes, encodePacked, keccak256, encodeAbiParameters, bytesToHex, concatHex, createPublicClient, http, encodeFunctionData, erc20Abi, bytesToBigInt, pad, toBytes, maxUint256, formatUnits, parseUnits } from 'viem';
4
4
  import mergeRace from '@async-generator/merge-race';
5
5
  import { gnosisChiado, gnosis, bscTestnet, bsc, soneium, baseSepolia, base, optimismSepolia, optimism, arbitrumSepolia, arbitrum, mainnet, sepolia } from 'viem/chains';
6
6
  import { hasWindow, isNode, env } from 'std-env';
@@ -10,6 +10,7 @@ import { WsProvider, ApiPromise } from '@polkadot/api';
10
10
  import { RpcWebSocketClient } from 'rpc-websocket-client';
11
11
  import { keccakAsU8a, decodeAddress, xxhashAsU8a } from '@polkadot/util-crypto';
12
12
  import { GraphQLClient } from 'graphql-request';
13
+ import { Decimal } from 'decimal.js';
13
14
  import { u8aToHex } from '@polkadot/util';
14
15
 
15
16
  var __defProp = Object.defineProperty;
@@ -3982,6 +3983,10 @@ var GetRequest = Struct({
3982
3983
  * Substrate Keys
3983
3984
  */
3984
3985
  keys: Vector(Vector(u8)),
3986
+ /*
3987
+ * The height of the state machine
3988
+ */
3989
+ height: u64,
3985
3990
  /*
3986
3991
  * Some application-specific metadata relating to this request
3987
3992
  */
@@ -4108,6 +4113,24 @@ var TimeoutMessage = Enum({
4108
4113
  requests: Vector(Request2)
4109
4114
  })
4110
4115
  });
4116
+ var GetRequestsWithProof = Struct({
4117
+ /*
4118
+ * Requests to be fetched
4119
+ */
4120
+ requests: Vector(GetRequest),
4121
+ /*
4122
+ * Membership batch proof for these requests
4123
+ */
4124
+ source: Proof,
4125
+ /*
4126
+ * Storage proof for these responses
4127
+ */
4128
+ response: Proof,
4129
+ /*
4130
+ * Signer information. Ideally should be their account identifier
4131
+ */
4132
+ signer: Vector(u8)
4133
+ });
4111
4134
  var Message = Enum({
4112
4135
  /*
4113
4136
  * A consensus update message
@@ -4856,6 +4879,8 @@ var EvmChain = class {
4856
4879
  ]
4857
4880
  });
4858
4881
  return encoded2;
4882
+ }).with({ kind: "GetRequest" }, (message2) => {
4883
+ throw new Error("GetResponse is not yet supported on Substrate chains");
4859
4884
  }).exhaustive();
4860
4885
  return encoded;
4861
4886
  }
@@ -5171,8 +5196,13 @@ var SubstrateChain = class {
5171
5196
  async submitUnsigned(message) {
5172
5197
  if (!this.api) throw new Error("API not initialized");
5173
5198
  const { api } = this;
5174
- const args = hexToBytes(this.encode(message)).slice(2);
5175
- const tx = api.tx.ismp.handleUnsigned(args);
5199
+ const args = encodeISMPMessage(message);
5200
+ let tx;
5201
+ if (message.kind === "GetRequest") {
5202
+ tx = api.tx.stateCoprocessor.handleUnsigned(args);
5203
+ } else {
5204
+ tx = api.tx.ismp.handleUnsigned(args);
5205
+ }
5176
5206
  return new Promise((resolve, reject) => {
5177
5207
  let unsub = () => {
5178
5208
  };
@@ -5315,6 +5345,18 @@ function convertIPostRequestToCodec(request) {
5315
5345
  }
5316
5346
  };
5317
5347
  }
5348
+ function convertIGetRequestToCodec(request) {
5349
+ return {
5350
+ source: convertStateMachineIdToEnum(request.source),
5351
+ dest: convertStateMachineIdToEnum(request.dest),
5352
+ from: Array.from(hexToBytes(request.from)),
5353
+ nonce: request.nonce,
5354
+ keys: request.keys.map((key) => Array.from(hexToBytes(key))),
5355
+ context: Array.from(hexToBytes(request.context)),
5356
+ timeoutTimestamp: request.timeoutTimestamp,
5357
+ height: request.height
5358
+ };
5359
+ }
5318
5360
  function encodeISMPMessage(message) {
5319
5361
  try {
5320
5362
  return match(message).with({ kind: "PostRequest" }, (message2) => {
@@ -5341,6 +5383,31 @@ function encodeISMPMessage(message) {
5341
5383
  ]);
5342
5384
  }).with({ kind: "GetResponse" }, (message2) => {
5343
5385
  throw new Error("GetResponse is not yet supported on Substrate chains");
5386
+ }).with({ kind: "GetRequest" }, (message2) => {
5387
+ return GetRequestsWithProof.enc({
5388
+ requests: message2.requests.map((request) => convertIGetRequestToCodec(request)),
5389
+ source: {
5390
+ height: {
5391
+ height: message2.source.height,
5392
+ id: {
5393
+ consensusStateId: Array.from(toBytes(message2.source.consensusStateId)),
5394
+ id: convertStateMachineIdToEnum(message2.source.stateMachine)
5395
+ }
5396
+ },
5397
+ proof: Array.from(hexToBytes(message2.source.proof))
5398
+ },
5399
+ response: {
5400
+ height: {
5401
+ height: message2.response.height,
5402
+ id: {
5403
+ consensusStateId: Array.from(toBytes(message2.response.consensusStateId)),
5404
+ id: convertStateMachineIdToEnum(message2.response.stateMachine)
5405
+ }
5406
+ },
5407
+ proof: Array.from(hexToBytes(message2.response.proof))
5408
+ },
5409
+ signer: Array.from(hexToBytes(message2.signer))
5410
+ });
5344
5411
  }).with({ kind: "TimeoutPostRequest" }, (message2) => {
5345
5412
  return Vector(Message).enc([
5346
5413
  {
@@ -11537,8 +11604,6 @@ var UNISWAP_V4_QUOTER_ABI = [
11537
11604
  inputs: [{ name: "revertData", type: "bytes", internalType: "bytes" }]
11538
11605
  }
11539
11606
  ];
11540
-
11541
- // src/protocols/intents.ts
11542
11607
  var IntentGateway = class {
11543
11608
  /**
11544
11609
  * Creates a new IntentGateway instance for cross-chain operations.
@@ -11624,6 +11689,7 @@ var IntentGateway = class {
11624
11689
  }))
11625
11690
  ];
11626
11691
  let destChainFillGas = 0n;
11692
+ let filledWithNativeToken = false;
11627
11693
  try {
11628
11694
  let protocolFeeInNativeToken = await this.quoteNative(postRequest, relayerFeeInDestFeeToken);
11629
11695
  protocolFeeInNativeToken = protocolFeeInNativeToken + protocolFeeInNativeToken * 50n / 10000n;
@@ -11636,6 +11702,7 @@ var IntentGateway = class {
11636
11702
  value: totalEthValue + protocolFeeInNativeToken,
11637
11703
  stateOverride: stateOverrides
11638
11704
  });
11705
+ filledWithNativeToken = true;
11639
11706
  } catch {
11640
11707
  console.warn(
11641
11708
  `Could not estimate gas for fill order with native token as fees for chain ${order.destChain}, now trying with fee token as fees`
@@ -11677,18 +11744,18 @@ var IntentGateway = class {
11677
11744
  sourceChainFeeTokenDecimals
11678
11745
  );
11679
11746
  const protocolFeeInSourceFeeToken = adjustFeeDecimals(
11680
- // Following baseIsmpModule.sol, the protocol fee is added to the relayer fee
11681
- await this.dest.quote(postRequest) + relayerFeeInDestFeeToken,
11747
+ await this.dest.quote(postRequest),
11682
11748
  destChainFeeTokenDecimals,
11683
11749
  sourceChainFeeTokenDecimals
11684
11750
  );
11685
- const totalEstimate = fillGasInSourceFeeToken + protocolFeeInSourceFeeToken + relayerFeeInSourceFeeToken;
11686
- const SWAP_OPERATIONS_BPS = 3500n;
11687
- const swapOperationsInFeeToken = totalEstimate * SWAP_OPERATIONS_BPS / 10000n;
11688
- const totalFeeTokenAmount = totalEstimate + swapOperationsInFeeToken;
11689
- const totalNativeTokenAmount = await this.convertFeeTokenToNative(totalFeeTokenAmount, "source");
11751
+ let totalEstimateInSourceFeeToken = fillGasInSourceFeeToken + protocolFeeInSourceFeeToken + relayerFeeInSourceFeeToken;
11752
+ if (!filledWithNativeToken) {
11753
+ totalEstimateInSourceFeeToken = totalEstimateInSourceFeeToken + totalEstimateInSourceFeeToken * 200n / 10000n;
11754
+ }
11755
+ let totalNativeTokenAmount = await this.convertFeeTokenToNative(totalEstimateInSourceFeeToken, "source");
11756
+ totalNativeTokenAmount = totalNativeTokenAmount + totalNativeTokenAmount * 200n / 10000n;
11690
11757
  return {
11691
- feeTokenAmount: totalFeeTokenAmount,
11758
+ feeTokenAmount: totalEstimateInSourceFeeToken,
11692
11759
  nativeTokenAmount: totalNativeTokenAmount,
11693
11760
  postRequestCalldata
11694
11761
  };
@@ -11698,8 +11765,7 @@ var IntentGateway = class {
11698
11765
  * Uses USD pricing to convert between fee token amounts and native token costs.
11699
11766
  *
11700
11767
  * @param feeTokenAmount - The amount in fee token (DAI)
11701
- * @param publicClient - The client for the chain to get native token info
11702
- * @param feeTokenDecimals - The decimal places of the fee token
11768
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the conversion
11703
11769
  * @returns The fee token amount converted to native token amount
11704
11770
  * @private
11705
11771
  */
@@ -11708,22 +11774,33 @@ var IntentGateway = class {
11708
11774
  const evmChainID = `EVM-${client.chain?.id}`;
11709
11775
  const wethAsset = this[getQuoteIn].config.getWrappedNativeAssetWithDecimals(evmChainID).asset;
11710
11776
  const feeToken = await this[getQuoteIn].getFeeTokenWithDecimals();
11711
- const { amountOut } = await this.findBestProtocolWithAmountIn(
11712
- getQuoteIn,
11713
- feeToken.address,
11714
- wethAsset,
11715
- feeTokenAmount,
11716
- "v2"
11717
- );
11718
- return amountOut;
11777
+ try {
11778
+ const { amountOut } = await this.findBestProtocolWithAmountIn(
11779
+ getQuoteIn,
11780
+ feeToken.address,
11781
+ wethAsset,
11782
+ feeTokenAmount,
11783
+ "v2"
11784
+ );
11785
+ if (amountOut === 0n) {
11786
+ throw new Error();
11787
+ }
11788
+ return amountOut;
11789
+ } catch {
11790
+ const nativeCurrency = client.chain?.nativeCurrency;
11791
+ const chainId = client.chain?.id;
11792
+ const feeTokenAmountDecimal = new Decimal(formatUnits(feeTokenAmount, feeToken.decimals));
11793
+ const nativeTokenPriceUsd = new Decimal(await fetchPrice(nativeCurrency?.symbol, chainId));
11794
+ const totalCostInNativeToken = feeTokenAmountDecimal.dividedBy(nativeTokenPriceUsd);
11795
+ return parseUnits(totalCostInNativeToken.toFixed(nativeCurrency?.decimals), nativeCurrency?.decimals);
11796
+ }
11719
11797
  }
11720
11798
  /**
11721
11799
  * Converts gas costs to the equivalent amount in the fee token (DAI).
11722
11800
  * Uses USD pricing to convert between native token gas costs and fee token amounts.
11723
11801
  *
11724
11802
  * @param gasEstimate - The estimated gas units
11725
- * @param publicClient - The client for the chain to get gas prices
11726
- * @param targetDecimals - The decimal places of the target fee token
11803
+ * @param gasEstimateIn - Whether to use "source" or "dest" chain for the conversion
11727
11804
  * @returns The gas cost converted to fee token amount
11728
11805
  * @private
11729
11806
  */
@@ -11734,15 +11811,36 @@ var IntentGateway = class {
11734
11811
  const evmChainID = `EVM-${client.chain?.id}`;
11735
11812
  const wethAddr = this[gasEstimateIn].config.getWrappedNativeAssetWithDecimals(evmChainID).asset;
11736
11813
  const feeToken = await this[gasEstimateIn].getFeeTokenWithDecimals();
11737
- const { amountOut } = await this.findBestProtocolWithAmountIn(
11738
- gasEstimateIn,
11739
- wethAddr,
11740
- feeToken.address,
11741
- gasCostInWei,
11742
- "v2"
11743
- );
11744
- return amountOut;
11814
+ try {
11815
+ const { amountOut } = await this.findBestProtocolWithAmountIn(
11816
+ gasEstimateIn,
11817
+ wethAddr,
11818
+ feeToken.address,
11819
+ gasCostInWei,
11820
+ "v2"
11821
+ );
11822
+ if (amountOut === 0n) {
11823
+ throw new Error();
11824
+ }
11825
+ return amountOut;
11826
+ } catch {
11827
+ const nativeCurrency = client.chain?.nativeCurrency;
11828
+ const chainId = client.chain?.id;
11829
+ const gasCostInToken = new Decimal(formatUnits(gasCostInWei, nativeCurrency?.decimals));
11830
+ const tokenPriceUsd = await fetchPrice(nativeCurrency?.symbol, chainId);
11831
+ const gasCostUsd = gasCostInToken.times(tokenPriceUsd);
11832
+ const feeTokenPriceUsd = new Decimal(1);
11833
+ const gasCostInFeeToken = gasCostUsd.dividedBy(feeTokenPriceUsd);
11834
+ return parseUnits(gasCostInFeeToken.toFixed(feeToken.decimals), feeToken.decimals);
11835
+ }
11745
11836
  }
11837
+ /**
11838
+ * Gets a quote for the native token cost of dispatching a post request.
11839
+ *
11840
+ * @param postRequest - The post request to quote
11841
+ * @param fee - The fee amount in fee token
11842
+ * @returns The native token amount required
11843
+ */
11746
11844
  async quoteNative(postRequest, fee) {
11747
11845
  const dispatchPost = {
11748
11846
  dest: toHex(postRequest.dest),
@@ -11764,7 +11862,7 @@ var IntentGateway = class {
11764
11862
  * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given a desired output amount.
11765
11863
  * Compares liquidity and pricing across different protocols and fee tiers.
11766
11864
  *
11767
- * @param chain - The chain identifier where the swap will occur
11865
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the swap
11768
11866
  * @param tokenIn - The address of the input token
11769
11867
  * @param tokenOut - The address of the output token
11770
11868
  * @param amountOut - The desired output amount
@@ -11929,10 +12027,11 @@ var IntentGateway = class {
11929
12027
  * Finds the best Uniswap protocol (V2, V3, or V4) for swapping tokens given an input amount.
11930
12028
  * Compares liquidity and pricing across different protocols and fee tiers.
11931
12029
  *
11932
- * @param chain - The chain identifier where the swap will occur
12030
+ * @param getQuoteIn - Whether to use "source" or "dest" chain for the swap
11933
12031
  * @param tokenIn - The address of the input token
11934
12032
  * @param tokenOut - The address of the output token
11935
12033
  * @param amountIn - The input amount to swap
12034
+ * @param selectedProtocol - Optional specific protocol to use ("v2", "v3", or "v4")
11936
12035
  * @returns Object containing the best protocol, expected output amount, and fee tier (for V3/V4)
11937
12036
  */
11938
12037
  async findBestProtocolWithAmountIn(getQuoteIn, tokenIn, tokenOut, amountIn, selectedProtocol) {