@moonbeam-network/mrl 4.0.23 → 4.1.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.
package/build/index.mjs CHANGED
@@ -16770,34 +16770,189 @@ async function getExecuteTransferData({
16770
16770
 
16771
16771
  // src/getTransferData/getTransferData.ts
16772
16772
  import {
16773
- ContractConfig as ContractConfig2,
16773
+ ContractConfig as ContractConfig3,
16774
16774
  ExtrinsicConfig,
16775
+ SnowbridgeConfig as SnowbridgeConfig2,
16775
16776
  WormholeConfig as WormholeConfig2
16776
16777
  } from "@moonbeam-network/xcm-builder";
16777
16778
  import {
16778
16779
  convertToChainDecimals as convertToChainDecimals2,
16779
- EvmService as EvmService2,
16780
+ EvmService as EvmService4,
16780
16781
  getDestinationData,
16781
- PolkadotService as PolkadotService2
16782
+ PolkadotService as PolkadotService3
16782
16783
  } from "@moonbeam-network/xcm-sdk";
16783
16784
  import {
16784
16785
  AssetAmount as AssetAmount3,
16785
- EvmChain,
16786
- EvmParachain as EvmParachain3
16786
+ EvmChain as EvmChain3,
16787
+ EvmParachain as EvmParachain4
16787
16788
  } from "@moonbeam-network/xcm-types";
16788
16789
  import { toBigInt as toBigInt3 } from "@moonbeam-network/xcm-utils";
16789
16790
  import Big2 from "big.js";
16790
16791
 
16791
- // src/getTransferData/getMoonChainData.ts
16792
- import { getMoonChain } from "@moonbeam-network/xcm-config";
16793
- import { getBalance, getDestinationFee } from "@moonbeam-network/xcm-sdk";
16792
+ // src/services/snowbridge/SnowbridgeService.ts
16794
16793
  import {
16795
- EvmParachain,
16796
- Parachain
16797
- } from "@moonbeam-network/xcm-types";
16794
+ ContractConfig,
16795
+ ERC20_ABI,
16796
+ GATEWAY_ABI
16797
+ } from "@moonbeam-network/xcm-builder";
16798
+ import { EvmService as EvmService2 } from "@moonbeam-network/xcm-sdk";
16799
+ import { EvmChain } from "@moonbeam-network/xcm-types";
16800
+ import { u8aToHex } from "@polkadot/util";
16801
+ import { decodeAddress } from "@polkadot/util-crypto";
16802
+ import { encodeFunctionData } from "viem";
16803
+ var SnowbridgeService = class _SnowbridgeService {
16804
+ chain;
16805
+ #evmService;
16806
+ #gatewayAddress;
16807
+ static create(chain2) {
16808
+ return new _SnowbridgeService(chain2);
16809
+ }
16810
+ constructor(chain2) {
16811
+ if (!EvmChain.is(chain2) || !chain2.contracts?.Gateway) {
16812
+ throw new Error(
16813
+ "Chain must be an EVMChain with the Gateway contract address configured for Snowbridge operations"
16814
+ );
16815
+ }
16816
+ this.chain = chain2;
16817
+ this.#gatewayAddress = chain2.contracts.Gateway;
16818
+ this.#evmService = EvmService2.create(chain2);
16819
+ }
16820
+ async checkAllowance(ownerAddress, tokenAddress, spenderAddress) {
16821
+ const allowance = await this.#evmService.client.readContract({
16822
+ abi: ERC20_ABI,
16823
+ address: tokenAddress,
16824
+ args: [ownerAddress, spenderAddress],
16825
+ functionName: "allowance"
16826
+ });
16827
+ if (typeof allowance !== "bigint") {
16828
+ throw new Error(
16829
+ `Could not get allowance on ${this.chain.name} for token ${tokenAddress}`
16830
+ );
16831
+ }
16832
+ return allowance;
16833
+ }
16834
+ async transfer(signer, transfer) {
16835
+ const { args } = transfer;
16836
+ const { tokenAddress, amount, requiresApproval } = args;
16837
+ if (!signer.account) {
16838
+ throw new Error("Signer account is required");
16839
+ }
16840
+ const contract = this.buildContractConfig(transfer);
16841
+ if (!requiresApproval) {
16842
+ return await this.#evmService.transfer(signer, contract);
16843
+ }
16844
+ const currentAllowance = await this.checkAllowance(
16845
+ signer.account.address,
16846
+ tokenAddress,
16847
+ this.#gatewayAddress
16848
+ );
16849
+ if (currentAllowance < amount) {
16850
+ await this.approve(signer, tokenAddress, this.#gatewayAddress, amount);
16851
+ }
16852
+ return await this.#evmService.transfer(signer, contract);
16853
+ }
16854
+ buildContractConfig(transfer) {
16855
+ const { args } = transfer;
16856
+ const {
16857
+ tokenAddress,
16858
+ destinationAddress,
16859
+ destinationParaId,
16860
+ amount,
16861
+ bridgeFeeAmount,
16862
+ requiresApproval
16863
+ } = args;
16864
+ const value = requiresApproval ? bridgeFeeAmount : amount + bridgeFeeAmount;
16865
+ const contractArgs = [
16866
+ tokenAddress,
16867
+ destinationParaId,
16868
+ {
16869
+ kind: 1,
16870
+ data: u8aToHex(decodeAddress(destinationAddress))
16871
+ },
16872
+ 0n,
16873
+ amount
16874
+ ];
16875
+ return new ContractConfig({
16876
+ address: this.#gatewayAddress,
16877
+ abi: GATEWAY_ABI,
16878
+ args: contractArgs,
16879
+ func: "sendToken",
16880
+ value,
16881
+ module: "Gateway"
16882
+ });
16883
+ }
16884
+ async approve(signer, tokenAddress, spenderAddress, amount) {
16885
+ const { request } = await this.#evmService.client.simulateContract({
16886
+ abi: ERC20_ABI,
16887
+ account: signer.account,
16888
+ address: tokenAddress,
16889
+ functionName: "approve",
16890
+ args: [spenderAddress, amount]
16891
+ });
16892
+ const hash = await signer.writeContract(request);
16893
+ await this.#evmService.client.waitForTransactionReceipt({
16894
+ hash
16895
+ });
16896
+ return hash;
16897
+ }
16898
+ async getFee(address, transfer) {
16899
+ const { args } = transfer;
16900
+ const { tokenAddress, amount, requiresApproval } = args;
16901
+ const contract = this.buildContractConfig(transfer);
16902
+ if (!requiresApproval) {
16903
+ return await this.#evmService.getFee(address, contract);
16904
+ }
16905
+ const currentAllowance = await this.checkAllowance(
16906
+ address,
16907
+ tokenAddress,
16908
+ this.#gatewayAddress
16909
+ );
16910
+ if (currentAllowance >= amount) {
16911
+ return await this.#evmService.getFee(address, contract);
16912
+ }
16913
+ return await this.estimateApproveAndSendFee(address, transfer);
16914
+ }
16915
+ async estimateApproveAndSendFee(address, transfer) {
16916
+ const { args } = transfer;
16917
+ const { tokenAddress, amount } = args;
16918
+ const contract = this.buildContractConfig(transfer);
16919
+ try {
16920
+ const approveData = encodeFunctionData({
16921
+ abi: ERC20_ABI,
16922
+ functionName: "approve",
16923
+ args: [this.#gatewayAddress, amount]
16924
+ });
16925
+ const approveGas = await this.#evmService.client.estimateGas({
16926
+ account: address,
16927
+ to: tokenAddress,
16928
+ data: approveData
16929
+ });
16930
+ const sendData = encodeFunctionData({
16931
+ abi: contract.abi,
16932
+ functionName: contract.func,
16933
+ args: contract.args
16934
+ });
16935
+ const sendGas = await this.#evmService.client.estimateGas({
16936
+ account: address,
16937
+ to: contract.address,
16938
+ data: sendData,
16939
+ value: contract.value
16940
+ });
16941
+ const gasPrice = await this.#evmService.client.getGasPrice();
16942
+ return (approveGas + sendGas) * gasPrice;
16943
+ } catch (error) {
16944
+ console.error("Error estimating approve + send fee:", error);
16945
+ return 0n;
16946
+ }
16947
+ }
16948
+ };
16949
+
16950
+ // src/getTransferData/getBridgeChainData.ts
16951
+ import { getBalance, getDestinationFee } from "@moonbeam-network/xcm-sdk";
16952
+ import { EvmParachain, Parachain } from "@moonbeam-network/xcm-types";
16798
16953
  import { getMultilocationDerivedAddresses } from "@moonbeam-network/xcm-utils";
16799
16954
  import { evmToAddress } from "@polkadot/util-crypto";
16800
- async function getMoonChainData({
16955
+ async function getBridgeChainData({
16801
16956
  route,
16802
16957
  sourceAddress,
16803
16958
  destinationAddress
@@ -16807,80 +16962,87 @@ async function getMoonChainData({
16807
16962
  `MRL config is not defined for source chain ${route.source.chain.name} and asset ${route.source.asset.originSymbol}`
16808
16963
  );
16809
16964
  }
16810
- const moonChain = getMoonChain(route.source.chain);
16811
- const moonChainAddress = getMoonChainAddress({
16812
- source: route.source.chain,
16813
- destination: route.destination.chain,
16965
+ const bridgeChain = route.mrl.bridgeChain.chain;
16966
+ const bridgeChainAddress = getBridgeChainAddress({
16967
+ route,
16814
16968
  sourceAddress,
16815
16969
  destinationAddress
16816
16970
  });
16817
16971
  const fee = await getDestinationFee({
16818
- address: moonChainAddress,
16972
+ address: bridgeChainAddress,
16819
16973
  asset: route.source.asset,
16820
- destination: moonChain,
16821
- fee: route.mrl.moonChain.fee.amount,
16822
- feeAsset: route.mrl.moonChain.fee.asset,
16974
+ destination: bridgeChain,
16975
+ fee: route.mrl.bridgeChain.fee.amount,
16976
+ feeAsset: route.mrl.bridgeChain.fee.asset,
16823
16977
  source: route.source.chain
16824
16978
  });
16825
16979
  const balance = await getBalance({
16826
- address: moonChainAddress,
16827
- asset: moonChain.getChainAsset(route.mrl.moonChain.asset),
16828
- builder: route.mrl.moonChain.balance,
16829
- chain: moonChain
16980
+ address: bridgeChainAddress,
16981
+ asset: bridgeChain.getChainAsset(route.mrl.bridgeChain.asset),
16982
+ builder: route.mrl.bridgeChain.balance,
16983
+ chain: bridgeChain
16830
16984
  });
16831
16985
  const feeBalance = await getBalance({
16832
- address: moonChainAddress,
16833
- asset: moonChain.getChainAsset(route.mrl.moonChain.fee.asset),
16834
- builder: route.mrl.moonChain.fee.balance,
16835
- chain: moonChain
16986
+ address: bridgeChainAddress,
16987
+ asset: bridgeChain.getChainAsset(route.mrl.bridgeChain.fee.asset),
16988
+ builder: route.mrl.bridgeChain.fee.balance,
16989
+ chain: bridgeChain
16836
16990
  });
16837
16991
  return {
16838
- address: moonChainAddress,
16992
+ address: bridgeChainAddress,
16839
16993
  balance,
16840
16994
  feeBalance,
16841
- chain: moonChain,
16995
+ chain: bridgeChain,
16842
16996
  fee
16843
16997
  };
16844
16998
  }
16845
- function getMoonChainAddress({
16846
- source,
16847
- destination,
16999
+ function getBridgeChainAddress({
17000
+ route,
16848
17001
  sourceAddress,
16849
17002
  destinationAddress
16850
17003
  }) {
16851
- const moonChain = getMoonChain(source);
16852
- const isDestinationMoonChain = moonChain.isEqual(destination);
16853
- const isSourceMoonChain = moonChain.isEqual(source);
16854
- let moonChainAddress = isDestinationMoonChain ? destinationAddress : sourceAddress;
16855
- if (Parachain.is(source) && !isSourceMoonChain) {
17004
+ const source = route.source.chain;
17005
+ const destination = route.destination.chain;
17006
+ const bridgeChain = route.mrl.bridgeChain.chain;
17007
+ const isDestinationBridgeChain = bridgeChain.isEqual(destination);
17008
+ const isSourceBridgeChain = bridgeChain.isEqual(source);
17009
+ let bridgeChainAddress = isDestinationBridgeChain ? destinationAddress : sourceAddress;
17010
+ if (Parachain.is(source) && !isSourceBridgeChain) {
16856
17011
  const isSourceEvmSigner = EvmParachain.is(source) && source.isEvmSigner;
16857
17012
  const { address20: computedOriginAccount } = getMultilocationDerivedAddresses({
16858
17013
  address: isSourceEvmSigner ? evmToAddress(sourceAddress) : sourceAddress,
16859
17014
  paraId: source.parachainId,
16860
17015
  isParents: true
16861
17016
  });
16862
- moonChainAddress = computedOriginAccount;
17017
+ bridgeChainAddress = computedOriginAccount;
16863
17018
  }
16864
- return moonChainAddress;
17019
+ return bridgeChainAddress;
16865
17020
  }
16866
17021
 
16867
17022
  // src/getTransferData/getSourceData.ts
16868
17023
  import {
16869
- ContractConfig,
17024
+ ContractConfig as ContractConfig2,
16870
17025
  MrlBuilder as MrlBuilder3,
17026
+ Provider as Provider2,
17027
+ SnowbridgeConfig,
17028
+ SubstrateQueryConfig,
16871
17029
  WormholeConfig
16872
17030
  } from "@moonbeam-network/xcm-builder";
16873
17031
  import {
17032
+ EvmService as EvmService3,
16874
17033
  getAssetMin,
16875
17034
  getBalance as getBalance2,
16876
17035
  getContractFee,
16877
17036
  getDestinationFeeBalance,
16878
17037
  getExistentialDeposit,
16879
17038
  getExtrinsicFee,
16880
- getMax
17039
+ getMax,
17040
+ PolkadotService as PolkadotService2
16881
17041
  } from "@moonbeam-network/xcm-sdk";
16882
17042
  import {
16883
- AssetAmount as AssetAmount2
17043
+ AssetAmount as AssetAmount2,
17044
+ EvmChain as EvmChain2,
17045
+ EvmParachain as EvmParachain3
16884
17046
  } from "@moonbeam-network/xcm-types";
16885
17047
  import { toBigInt as toBigInt2 } from "@moonbeam-network/xcm-utils";
16886
17048
 
@@ -16888,11 +17050,11 @@ import { toBigInt as toBigInt2 } from "@moonbeam-network/xcm-utils";
16888
17050
  import {
16889
17051
  BATCH_CONTRACT_ABI,
16890
17052
  BATCH_CONTRACT_ADDRESS,
16891
- ERC20_ABI,
16892
- MrlBuilder as MrlBuilder2
17053
+ ERC20_ABI as ERC20_ABI2,
17054
+ MrlBuilder as MrlBuilder2,
17055
+ Provider
16893
17056
  } from "@moonbeam-network/xcm-builder";
16894
17057
  import {
16895
- getMoonChain as getMoonChain2,
16896
17058
  moonbaseAlpha,
16897
17059
  moonbeam
16898
17060
  } from "@moonbeam-network/xcm-config";
@@ -16909,33 +17071,33 @@ import {
16909
17071
  import Big from "big.js";
16910
17072
  import {
16911
17073
  createPublicClient as createPublicClient2,
16912
- encodeFunctionData,
17074
+ encodeFunctionData as encodeFunctionData2,
16913
17075
  http as http2
16914
17076
  } from "viem";
16915
17077
  var MOON_CHAIN_AUTOMATIC_GAS_ESTIMATION = {
16916
17078
  [moonbeam.key]: 1273110n,
16917
17079
  [moonbaseAlpha.key]: 1470417n
16918
17080
  };
16919
- function getMoonChainFeeValueOnSource({
17081
+ function getBridgeChainFeeValueOnSource({
16920
17082
  destinationData,
16921
- moonChainData,
17083
+ bridgeChainData,
16922
17084
  sourceData
16923
17085
  }) {
16924
17086
  const isSourceParachain = EvmParachain2.isAnyParachain(sourceData.chain);
16925
- const isDestinationMoonChain = destinationData.chain.isEqual(
16926
- moonChainData.chain
17087
+ const isDestinationBridgeChain = destinationData.chain.isEqual(
17088
+ bridgeChainData.chain
16927
17089
  );
16928
- const isSameAssetPayingMoonChainFee = sourceData.balance.isSame(
16929
- moonChainData.fee
17090
+ const isSameAssetPayingBridgeChainFee = sourceData.balance.isSame(
17091
+ bridgeChainData.fee
16930
17092
  );
16931
- return !isDestinationMoonChain && isSourceParachain && isSameAssetPayingMoonChainFee ? convertToChainDecimals({
16932
- asset: moonChainData.fee,
16933
- target: sourceData.chain.getChainAsset(moonChainData.fee)
17093
+ return !isDestinationBridgeChain && isSourceParachain && isSameAssetPayingBridgeChainFee ? convertToChainDecimals({
17094
+ asset: bridgeChainData.fee,
17095
+ target: sourceData.chain.getChainAsset(bridgeChainData.fee)
16934
17096
  }).toBig() : Big(0);
16935
17097
  }
16936
17098
  function getMrlMin({
16937
17099
  destinationData,
16938
- moonChainData,
17100
+ bridgeChainData,
16939
17101
  sourceData
16940
17102
  }) {
16941
17103
  const minInDestination = getMin(destinationData);
@@ -16945,16 +17107,19 @@ function getMrlMin({
16945
17107
  amount: minInDestination.amount
16946
17108
  }
16947
17109
  );
16948
- const moonChainFee = getMoonChainFeeValueOnSource({
17110
+ const bridgeChainFee = getBridgeChainFeeValueOnSource({
16949
17111
  destinationData,
16950
- moonChainData,
17112
+ bridgeChainData,
16951
17113
  sourceData
16952
17114
  });
16953
- const relayerFee = sourceData.relayerFee?.amount ? sourceData.relayerFee.toBig() : Big(0);
17115
+ const relayerFee = sourceData.otherFees?.relayer?.amount ? sourceData.otherFees.relayer.toBig() : Big(0);
16954
17116
  return min.copyWith({
16955
- amount: BigInt(min.toBig().add(moonChainFee).add(relayerFee).toFixed())
17117
+ amount: BigInt(min.toBig().add(bridgeChainFee).add(relayerFee).toFixed())
16956
17118
  });
16957
17119
  }
17120
+ function requiresTransact(route) {
17121
+ return route.mrl?.transfer.provider === Provider.Wormhole && EvmParachain2.isAnyParachain(route.source.chain);
17122
+ }
16958
17123
  async function buildTransfer(params) {
16959
17124
  const { route } = params;
16960
17125
  if (!route.mrl) {
@@ -16970,11 +17135,12 @@ async function buildTransfer(params) {
16970
17135
  const builderParams = await getMrlBuilderParams(params);
16971
17136
  return route.mrl.transfer.build({
16972
17137
  ...builderParams,
16973
- transact: EvmParachain2.isAnyParachain(route.source.chain) ? await getTransact(builderParams) : void 0
17138
+ transact: requiresTransact(route) ? await getTransact(builderParams) : void 0
16974
17139
  });
16975
17140
  }
16976
17141
  async function getMrlBuilderParams({
16977
17142
  asset,
17143
+ protocolFee,
16978
17144
  destinationAddress,
16979
17145
  feeAsset,
16980
17146
  isAutomatic,
@@ -16989,22 +17155,23 @@ async function getMrlBuilderParams({
16989
17155
  }
16990
17156
  const source = route.source.chain;
16991
17157
  const destination = route.destination.chain;
16992
- const moonChain = getMoonChain2(source);
16993
- const [sourceApi, destinationApi, moonApi] = await Promise.all([
17158
+ const bridgeChain = route.mrl.bridgeChain.chain;
17159
+ const [sourceApi, destinationApi, bridgeApi] = await Promise.all([
16994
17160
  EvmParachain2.isAnyParachain(source) ? getPolkadotApi(source.ws) : void 0,
16995
17161
  EvmParachain2.isAnyParachain(destination) ? getPolkadotApi(destination.ws) : void 0,
16996
- getPolkadotApi(moonChain.ws)
17162
+ getPolkadotApi(bridgeChain.ws)
16997
17163
  ]);
16998
17164
  return {
16999
17165
  asset,
17166
+ protocolFee,
17000
17167
  destination,
17001
17168
  destinationAddress,
17002
17169
  destinationApi,
17003
17170
  fee: feeAsset,
17004
17171
  isAutomatic,
17005
- moonApi,
17006
- moonAsset: moonChain.nativeAsset,
17007
- moonChain,
17172
+ moonApi: bridgeApi,
17173
+ moonAsset: bridgeChain.nativeAsset,
17174
+ bridgeChain,
17008
17175
  sendOnlyRemoteExecution,
17009
17176
  source,
17010
17177
  sourceAddress,
@@ -17012,9 +17179,9 @@ async function getMrlBuilderParams({
17012
17179
  };
17013
17180
  }
17014
17181
  async function getTransact(params) {
17015
- const { sourceAddress, source, moonChain } = params;
17016
- const polkadot = await PolkadotService.create(moonChain);
17017
- const moonGasLimit = await getMoonGasLimit(params);
17182
+ const { sourceAddress, source, bridgeChain } = params;
17183
+ const polkadot = await PolkadotService.create(bridgeChain);
17184
+ const bridgeChainGasLimit = await getBridgeChainGasLimit(params);
17018
17185
  if (!EvmParachain2.isAnyParachain(source)) {
17019
17186
  throw new Error("Source chain must be Parachain or EvmParachain");
17020
17187
  }
@@ -17023,7 +17190,7 @@ async function getTransact(params) {
17023
17190
  paraId: source.parachainId,
17024
17191
  isParents: true
17025
17192
  });
17026
- const extrinsic = MrlBuilder2().wormhole().extrinsic().ethereumXcm().transact().build({ ...params, moonGasLimit });
17193
+ const extrinsic = MrlBuilder2().wormhole().extrinsic().ethereumXcm().transact().build({ ...params, bridgeChainGasLimit });
17027
17194
  const { weight } = await polkadot.getPaymentInfo(address20, extrinsic);
17028
17195
  return {
17029
17196
  call: polkadot.getExtrinsicCallHash(extrinsic),
@@ -17033,13 +17200,16 @@ async function getTransact(params) {
17033
17200
  }
17034
17201
  };
17035
17202
  }
17036
- async function getMoonGasLimit(params) {
17037
- const { asset, isAutomatic, moonChain, source, sourceAddress } = params;
17203
+ async function getBridgeChainGasLimit(params) {
17204
+ const { asset, isAutomatic, bridgeChain, source, sourceAddress } = params;
17038
17205
  if (!EvmParachain2.isAnyParachain(source)) {
17039
17206
  throw new Error("Source chain must be Parachain or EvmParachain");
17040
17207
  }
17208
+ if (!EvmParachain2.is(bridgeChain)) {
17209
+ throw new Error("Bridge chain must be an EvmParachain");
17210
+ }
17041
17211
  const client = createPublicClient2({
17042
- chain: moonChain.getViemChain(),
17212
+ chain: bridgeChain.getViemChain(),
17043
17213
  transport: http2()
17044
17214
  });
17045
17215
  const { address20 } = getMultilocationDerivedAddresses2({
@@ -17048,28 +17218,28 @@ async function getMoonGasLimit(params) {
17048
17218
  isParents: true
17049
17219
  });
17050
17220
  if (isAutomatic) {
17051
- return MOON_CHAIN_AUTOMATIC_GAS_ESTIMATION[moonChain.key] * 110n / 100n;
17221
+ return MOON_CHAIN_AUTOMATIC_GAS_ESTIMATION[bridgeChain.key] * 110n / 100n;
17052
17222
  }
17053
17223
  const contract = MrlBuilder2().wormhole().contract().TokenBridge().transferTokens().build({
17054
17224
  ...params,
17055
17225
  asset: asset.copyWith({ amount: 0n })
17056
17226
  });
17057
- const approveTx = encodeFunctionData({
17058
- abi: ERC20_ABI,
17227
+ const approveTx = encodeFunctionData2({
17228
+ abi: ERC20_ABI2,
17059
17229
  functionName: "approve",
17060
17230
  args: [contract.address, 0n]
17061
17231
  });
17062
- const tokenAddressOnMoonChain = moonChain.getChainAsset(asset).address;
17063
- if (!tokenAddressOnMoonChain) {
17232
+ const tokenAddressOnBridgeChain = bridgeChain.getChainAsset(asset).address;
17233
+ if (!tokenAddressOnBridgeChain) {
17064
17234
  throw new Error(
17065
- `Asset ${asset.symbol} does not have a token address on chain ${moonChain.name}`
17235
+ `Asset ${asset.symbol} does not have a token address on chain ${bridgeChain.name}`
17066
17236
  );
17067
17237
  }
17068
- const batchAll = encodeFunctionData({
17238
+ const batchAll = encodeFunctionData2({
17069
17239
  abi: BATCH_CONTRACT_ABI,
17070
17240
  functionName: "batchAll",
17071
17241
  args: [
17072
- [tokenAddressOnMoonChain, contract.address],
17242
+ [tokenAddressOnBridgeChain, contract.address],
17073
17243
  [0n, 0n],
17074
17244
  // Value to send for each call
17075
17245
  [approveTx, contract.encodeFunctionData()],
@@ -17085,6 +17255,11 @@ async function getMoonGasLimit(params) {
17085
17255
  });
17086
17256
  return gasEstimation * 110n / 100n;
17087
17257
  }
17258
+ function getAmountForTransferSimulation(balance, protocolFee) {
17259
+ return balance.copyWith({
17260
+ amount: balance.amount - protocolFee.amount > 0 ? balance.amount - protocolFee.amount : 0n
17261
+ });
17262
+ }
17088
17263
 
17089
17264
  // src/getTransferData/getSourceData.ts
17090
17265
  async function getSourceData({
@@ -17100,6 +17275,7 @@ async function getSourceData({
17100
17275
  );
17101
17276
  }
17102
17277
  const source = route.source.chain;
17278
+ const destination = route.destination.chain;
17103
17279
  const asset = source.getChainAsset(route.source.asset);
17104
17280
  const feeAsset = route.source.fee ? source.getChainAsset(route.source.fee.asset) : asset;
17105
17281
  const balance = await getBalance2({
@@ -17120,7 +17296,7 @@ async function getSourceData({
17120
17296
  route,
17121
17297
  sourceAddress
17122
17298
  });
17123
- const moonChainFeeBalance = await getMoonChainFeeBalance({
17299
+ const bridgeChainFeeBalance = await getBridgeChainFeeBalance({
17124
17300
  balance,
17125
17301
  feeBalance,
17126
17302
  route,
@@ -17132,8 +17308,18 @@ async function getSourceData({
17132
17308
  builder: route.source.min,
17133
17309
  chain: source
17134
17310
  });
17311
+ const protocolFee = await getProtocolFee({
17312
+ source,
17313
+ destination,
17314
+ asset,
17315
+ feeAsset,
17316
+ balance,
17317
+ protocolFee: route.source.protocolFee,
17318
+ address: destinationAddress
17319
+ });
17135
17320
  const transfer = await buildTransfer({
17136
- asset: balance,
17321
+ asset: getAmountForTransferSimulation(balance, protocolFee),
17322
+ protocolFee,
17137
17323
  destinationAddress,
17138
17324
  feeAsset: feeBalance,
17139
17325
  isAutomatic,
@@ -17170,13 +17356,16 @@ async function getSourceData({
17170
17356
  chain: source,
17171
17357
  destinationFee,
17172
17358
  destinationFeeBalance,
17173
- moonChainFeeBalance,
17359
+ bridgeChainFeeBalance,
17174
17360
  existentialDeposit,
17175
17361
  fee,
17176
17362
  feeBalance,
17177
17363
  max,
17178
17364
  min,
17179
- relayerFee
17365
+ otherFees: {
17366
+ protocol: protocolFee,
17367
+ relayer: relayerFee?.amount ? relayerFee : void 0
17368
+ }
17180
17369
  };
17181
17370
  }
17182
17371
  async function getFee({
@@ -17193,16 +17382,33 @@ async function getFee({
17193
17382
  amount: 0n
17194
17383
  });
17195
17384
  }
17196
- if (ContractConfig.is(transfer)) {
17197
- return getContractFee({
17198
- address: sourceAddress,
17199
- balance,
17200
- chain: chain2,
17201
- contract: transfer,
17202
- destinationFee,
17203
- feeBalance,
17204
- feeConfig
17205
- });
17385
+ if (SnowbridgeConfig.is(transfer)) {
17386
+ const snowbridge = SnowbridgeService.create(chain2);
17387
+ try {
17388
+ const feeAmount = await snowbridge.getFee(sourceAddress, transfer);
17389
+ return AssetAmount2.fromChainAsset(chain2.getChainAsset(feeBalance), {
17390
+ amount: feeAmount
17391
+ });
17392
+ } catch (error) {
17393
+ console.error(error);
17394
+ return feeBalance.copyWith({ amount: 0n });
17395
+ }
17396
+ }
17397
+ if (ContractConfig2.is(transfer)) {
17398
+ try {
17399
+ return getContractFee({
17400
+ address: sourceAddress,
17401
+ balance,
17402
+ chain: chain2,
17403
+ contract: transfer,
17404
+ destinationFee,
17405
+ feeBalance,
17406
+ feeConfig
17407
+ });
17408
+ } catch (error) {
17409
+ console.error(error);
17410
+ return feeBalance.copyWith({ amount: 0n });
17411
+ }
17206
17412
  }
17207
17413
  return getExtrinsicFee({
17208
17414
  address: sourceAddress,
@@ -17223,19 +17429,25 @@ async function getRelayerFee({
17223
17429
  sourceAddress,
17224
17430
  transfer
17225
17431
  }) {
17432
+ if (route.mrl.transfer.provider === Provider2.Snowbridge || SnowbridgeConfig.is(transfer)) {
17433
+ return void 0;
17434
+ }
17226
17435
  if (WormholeConfig.is(transfer)) {
17227
17436
  return getWormholeFee({ asset, chain: chain2, config: transfer });
17228
17437
  }
17229
- const builderParams = await getMrlBuilderParams({
17230
- asset,
17231
- destinationAddress,
17232
- feeAsset,
17233
- isAutomatic,
17234
- route,
17235
- sourceAddress
17236
- });
17237
- const wormholeConfig = MrlBuilder3().wormhole().wormhole().tokenTransfer().build(builderParams);
17238
- return getWormholeFee({ asset, chain: chain2, config: wormholeConfig });
17438
+ if (route.mrl.transfer.provider === Provider2.Wormhole) {
17439
+ const builderParams = await getMrlBuilderParams({
17440
+ asset,
17441
+ destinationAddress,
17442
+ feeAsset,
17443
+ isAutomatic,
17444
+ route,
17445
+ sourceAddress
17446
+ });
17447
+ const wormholeConfig = MrlBuilder3().wormhole().wormhole().tokenTransfer().build(builderParams);
17448
+ return getWormholeFee({ asset, chain: chain2, config: wormholeConfig });
17449
+ }
17450
+ return;
17239
17451
  }
17240
17452
  async function getWormholeFee({
17241
17453
  asset,
@@ -17252,33 +17464,78 @@ async function getWormholeFee({
17252
17464
  }
17253
17465
  return;
17254
17466
  }
17255
- async function getMoonChainFeeBalance({
17467
+ async function getBridgeChainFeeBalance({
17256
17468
  balance,
17257
17469
  feeBalance,
17258
17470
  route,
17259
17471
  sourceAddress
17260
17472
  }) {
17261
- if (!route.source.moonChainFee) {
17473
+ if (!route.source.bridgeChainFee) {
17262
17474
  return void 0;
17263
17475
  }
17264
- if (route.mrl?.moonChain.fee.asset.isEqual(balance)) {
17476
+ if (route.mrl?.bridgeChain.fee.asset.isEqual(balance)) {
17265
17477
  return balance;
17266
17478
  }
17267
- if (route.mrl?.moonChain.fee.asset.isEqual(feeBalance)) {
17479
+ if (route.mrl?.bridgeChain.fee.asset.isEqual(feeBalance)) {
17268
17480
  return feeBalance;
17269
17481
  }
17270
- if (!route.source.moonChainFee.balance) {
17482
+ if (!route.source.bridgeChainFee.balance) {
17271
17483
  throw new Error(
17272
- "BalanceBuilder must be defined for source.moonChainFee.balance for MrlAssetRoute"
17484
+ "BalanceBuilder must be defined for source.bridgeChainFee.balance for MrlAssetRoute"
17273
17485
  );
17274
17486
  }
17275
17487
  return getBalance2({
17276
17488
  address: sourceAddress,
17277
- asset: route.source.chain.getChainAsset(route.source.moonChainFee.asset),
17278
- builder: route.source.moonChainFee.balance,
17489
+ asset: route.source.chain.getChainAsset(route.source.bridgeChainFee.asset),
17490
+ builder: route.source.bridgeChainFee.balance,
17279
17491
  chain: route.source.chain
17280
17492
  });
17281
17493
  }
17494
+ async function getProtocolFee({
17495
+ address,
17496
+ asset,
17497
+ feeAsset,
17498
+ balance,
17499
+ protocolFee,
17500
+ destination,
17501
+ source
17502
+ }) {
17503
+ if (typeof protocolFee === "number") {
17504
+ return AssetAmount2.fromChainAsset(asset, {
17505
+ amount: protocolFee
17506
+ });
17507
+ }
17508
+ const config = protocolFee?.build({
17509
+ address,
17510
+ asset,
17511
+ feeAsset,
17512
+ balance,
17513
+ destination,
17514
+ source
17515
+ });
17516
+ if (ContractConfig2.is(config) && EvmChain2.is(source)) {
17517
+ const evm = EvmService3.create(source);
17518
+ const amount = await evm.read(config);
17519
+ if (typeof amount !== "bigint") {
17520
+ throw new Error(
17521
+ `Error getting bridge fee: expected bigint from contract call, but received ${typeof amount}. `
17522
+ );
17523
+ }
17524
+ return AssetAmount2.fromChainAsset(feeAsset, {
17525
+ amount
17526
+ });
17527
+ }
17528
+ if (SubstrateQueryConfig.is(config) && EvmParachain3.isAnyParachain(source)) {
17529
+ const polkadot = await PolkadotService2.create(source);
17530
+ const amount = await polkadot.query(config);
17531
+ return AssetAmount2.fromChainAsset(feeAsset, {
17532
+ amount
17533
+ });
17534
+ }
17535
+ return AssetAmount2.fromChainAsset(feeAsset, {
17536
+ amount: 0n
17537
+ });
17538
+ }
17282
17539
 
17283
17540
  // src/getTransferData/getTransferData.ts
17284
17541
  async function getTransferData({
@@ -17307,7 +17564,7 @@ async function getTransferData({
17307
17564
  destinationFee,
17308
17565
  sourceAddress
17309
17566
  });
17310
- const moonChainData = await getMoonChainData({
17567
+ const bridgeChainData = await getBridgeChainData({
17311
17568
  route,
17312
17569
  sourceAddress,
17313
17570
  destinationAddress
@@ -17319,14 +17576,14 @@ async function getTransferData({
17319
17576
  const bigAmount = Big2(
17320
17577
  toBigInt3(amount, sourceData.balance.decimals).toString()
17321
17578
  );
17322
- const fee = getMoonChainFeeValueOnSource({
17579
+ const fee = getBridgeChainFeeValueOnSource({
17323
17580
  destinationData,
17324
- moonChainData,
17581
+ bridgeChainData,
17325
17582
  sourceData
17326
17583
  });
17327
17584
  const result = bigAmount.minus(
17328
17585
  isSameAssetPayingDestinationFee ? destinationFee.toBig() : Big2(0)
17329
- ).minus(fee).minus(sourceData.relayerFee?.toBig() || Big2(0));
17586
+ ).minus(fee).minus(sourceData.otherFees?.relayer?.toBig() || Big2(0));
17330
17587
  return sourceData.balance.copyWith({
17331
17588
  amount: result.lt(0) ? 0n : BigInt(result.toFixed())
17332
17589
  });
@@ -17335,10 +17592,10 @@ async function getTransferData({
17335
17592
  max: sourceData.max,
17336
17593
  min: getMrlMin({
17337
17594
  destinationData,
17338
- moonChainData,
17595
+ bridgeChainData,
17339
17596
  sourceData
17340
17597
  }),
17341
- moonChain: moonChainData,
17598
+ bridgeChain: bridgeChainData,
17342
17599
  source: sourceData,
17343
17600
  async transfer({
17344
17601
  amount,
@@ -17361,6 +17618,7 @@ async function getTransferData({
17361
17618
  );
17362
17619
  const transfer = await buildTransfer({
17363
17620
  asset,
17621
+ protocolFee: sourceData.otherFees?.protocol,
17364
17622
  destinationAddress,
17365
17623
  feeAsset,
17366
17624
  isAutomatic: isAutomatic2,
@@ -17368,19 +17626,19 @@ async function getTransferData({
17368
17626
  sendOnlyRemoteExecution,
17369
17627
  sourceAddress
17370
17628
  });
17371
- if (ContractConfig2.is(transfer) && (EvmChain.is(source) || EvmParachain3.is(source))) {
17629
+ if (ContractConfig3.is(transfer) && (EvmChain3.is(source) || EvmParachain4.is(source))) {
17372
17630
  if (!evmSigner) {
17373
17631
  throw new Error("EVM Signer must be provided");
17374
17632
  }
17375
- const evm = EvmService2.create(source);
17633
+ const evm = EvmService4.create(source);
17376
17634
  const hash = await evm.transfer(evmSigner, transfer);
17377
17635
  return [hash];
17378
17636
  }
17379
- if (ExtrinsicConfig.is(transfer) && EvmParachain3.isAnyParachain(source)) {
17637
+ if (ExtrinsicConfig.is(transfer) && EvmParachain4.isAnyParachain(source)) {
17380
17638
  if (!polkadotSigner) {
17381
17639
  throw new Error("Polkadot signer must be provided");
17382
17640
  }
17383
- const polkadot = await PolkadotService2.create(source);
17641
+ const polkadot = await PolkadotService3.create(source);
17384
17642
  const hash = await polkadot.transfer(
17385
17643
  sourceAddress,
17386
17644
  transfer,
@@ -17389,13 +17647,21 @@ async function getTransferData({
17389
17647
  );
17390
17648
  return [hash];
17391
17649
  }
17392
- if (WormholeConfig2.is(transfer) && (EvmChain.is(source) || EvmParachain3.is(source))) {
17650
+ if (WormholeConfig2.is(transfer) && (EvmChain3.is(source) || EvmParachain4.is(source))) {
17393
17651
  if (!evmSigner) {
17394
17652
  throw new Error("EVM Signer must be provided");
17395
17653
  }
17396
17654
  const wh = WormholeService.create(source);
17397
17655
  return wh.transfer(evmSigner, transfer);
17398
17656
  }
17657
+ if (SnowbridgeConfig2.is(transfer) && (EvmChain3.is(source) || EvmParachain4.is(source))) {
17658
+ if (!evmSigner) {
17659
+ throw new Error("EVM Signer must be provided");
17660
+ }
17661
+ const snowbridge = SnowbridgeService.create(source);
17662
+ const hash = await snowbridge.transfer(evmSigner, transfer);
17663
+ return [hash];
17664
+ }
17399
17665
  throw new Error("Either contract or extrinsic must be provided");
17400
17666
  }
17401
17667
  };