@moonbeam-network/mrl 1.0.0-dev.271 → 1.0.0-dev.272
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.d.ts +13 -7
- package/build/index.mjs +380 -125
- package/build/index.mjs.map +1 -1
- package/package.json +6 -6
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
|
|
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
|
|
16780
|
+
EvmService as EvmService4,
|
|
16780
16781
|
getDestinationData,
|
|
16781
|
-
PolkadotService as
|
|
16782
|
+
PolkadotService as PolkadotService3
|
|
16782
16783
|
} from "@moonbeam-network/xcm-sdk";
|
|
16783
16784
|
import {
|
|
16784
16785
|
AssetAmount as AssetAmount3,
|
|
16785
|
-
EvmChain,
|
|
16786
|
-
EvmParachain as
|
|
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/
|
|
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
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
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
|
|
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
|
|
16811
|
-
const
|
|
16812
|
-
|
|
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:
|
|
16972
|
+
address: bridgeChainAddress,
|
|
16819
16973
|
asset: route.source.asset,
|
|
16820
|
-
destination:
|
|
16821
|
-
fee: route.mrl.
|
|
16822
|
-
feeAsset: route.mrl.
|
|
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:
|
|
16827
|
-
asset:
|
|
16828
|
-
builder: route.mrl.
|
|
16829
|
-
chain:
|
|
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:
|
|
16833
|
-
asset:
|
|
16834
|
-
builder: route.mrl.
|
|
16835
|
-
chain:
|
|
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:
|
|
16992
|
+
address: bridgeChainAddress,
|
|
16839
16993
|
balance,
|
|
16840
16994
|
feeBalance,
|
|
16841
|
-
chain:
|
|
16995
|
+
chain: bridgeChain,
|
|
16842
16996
|
fee
|
|
16843
16997
|
};
|
|
16844
16998
|
}
|
|
16845
|
-
function
|
|
16846
|
-
|
|
16847
|
-
destination,
|
|
16999
|
+
function getBridgeChainAddress({
|
|
17000
|
+
route,
|
|
16848
17001
|
sourceAddress,
|
|
16849
17002
|
destinationAddress
|
|
16850
17003
|
}) {
|
|
16851
|
-
const
|
|
16852
|
-
const
|
|
16853
|
-
const
|
|
16854
|
-
|
|
16855
|
-
|
|
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
|
-
|
|
17017
|
+
bridgeChainAddress = computedOriginAccount;
|
|
16863
17018
|
}
|
|
16864
|
-
return
|
|
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
|
|
17081
|
+
function getBridgeChainFeeValueOnSource({
|
|
16920
17082
|
destinationData,
|
|
16921
|
-
|
|
17083
|
+
bridgeChainData,
|
|
16922
17084
|
sourceData
|
|
16923
17085
|
}) {
|
|
16924
17086
|
const isSourceParachain = EvmParachain2.isAnyParachain(sourceData.chain);
|
|
16925
|
-
const
|
|
16926
|
-
|
|
17087
|
+
const isDestinationBridgeChain = destinationData.chain.isEqual(
|
|
17088
|
+
bridgeChainData.chain
|
|
16927
17089
|
);
|
|
16928
|
-
const
|
|
16929
|
-
|
|
17090
|
+
const isSameAssetPayingBridgeChainFee = sourceData.balance.isSame(
|
|
17091
|
+
bridgeChainData.fee
|
|
16930
17092
|
);
|
|
16931
|
-
return !
|
|
16932
|
-
asset:
|
|
16933
|
-
target: sourceData.chain.getChainAsset(
|
|
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
|
-
|
|
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
|
|
17110
|
+
const bridgeChainFee = getBridgeChainFeeValueOnSource({
|
|
16949
17111
|
destinationData,
|
|
16950
|
-
|
|
17112
|
+
bridgeChainData,
|
|
16951
17113
|
sourceData
|
|
16952
17114
|
});
|
|
16953
|
-
const relayerFee = sourceData.
|
|
17115
|
+
const relayerFee = sourceData.otherFees?.relayer?.amount ? sourceData.otherFees.relayer.toBig() : Big(0);
|
|
16954
17116
|
return min.copyWith({
|
|
16955
|
-
amount: BigInt(min.toBig().add(
|
|
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:
|
|
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
|
|
16993
|
-
const [sourceApi, destinationApi,
|
|
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(
|
|
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:
|
|
17007
|
-
|
|
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,
|
|
17016
|
-
const polkadot = await PolkadotService.create(
|
|
17017
|
-
const
|
|
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,
|
|
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
|
|
17037
|
-
const { asset, isAutomatic,
|
|
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:
|
|
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[
|
|
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 =
|
|
17058
|
-
abi:
|
|
17227
|
+
const approveTx = encodeFunctionData2({
|
|
17228
|
+
abi: ERC20_ABI2,
|
|
17059
17229
|
functionName: "approve",
|
|
17060
17230
|
args: [contract.address, 0n]
|
|
17061
17231
|
});
|
|
17062
|
-
const
|
|
17063
|
-
if (!
|
|
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 ${
|
|
17235
|
+
`Asset ${asset.symbol} does not have a token address on chain ${bridgeChain.name}`
|
|
17066
17236
|
);
|
|
17067
17237
|
}
|
|
17068
|
-
const batchAll =
|
|
17238
|
+
const batchAll = encodeFunctionData2({
|
|
17069
17239
|
abi: BATCH_CONTRACT_ABI,
|
|
17070
17240
|
functionName: "batchAll",
|
|
17071
17241
|
args: [
|
|
17072
|
-
[
|
|
17242
|
+
[tokenAddressOnBridgeChain, contract.address],
|
|
17073
17243
|
[0n, 0n],
|
|
17074
17244
|
// Value to send for each call
|
|
17075
17245
|
[approveTx, contract.encodeFunctionData()],
|
|
@@ -17100,6 +17270,7 @@ async function getSourceData({
|
|
|
17100
17270
|
);
|
|
17101
17271
|
}
|
|
17102
17272
|
const source = route.source.chain;
|
|
17273
|
+
const destination = route.destination.chain;
|
|
17103
17274
|
const asset = source.getChainAsset(route.source.asset);
|
|
17104
17275
|
const feeAsset = route.source.fee ? source.getChainAsset(route.source.fee.asset) : asset;
|
|
17105
17276
|
const balance = await getBalance2({
|
|
@@ -17120,7 +17291,7 @@ async function getSourceData({
|
|
|
17120
17291
|
route,
|
|
17121
17292
|
sourceAddress
|
|
17122
17293
|
});
|
|
17123
|
-
const
|
|
17294
|
+
const bridgeChainFeeBalance = await getBridgeChainFeeBalance({
|
|
17124
17295
|
balance,
|
|
17125
17296
|
feeBalance,
|
|
17126
17297
|
route,
|
|
@@ -17132,8 +17303,19 @@ async function getSourceData({
|
|
|
17132
17303
|
builder: route.source.min,
|
|
17133
17304
|
chain: source
|
|
17134
17305
|
});
|
|
17306
|
+
const protocolFee = await getProtocolFee({
|
|
17307
|
+
source,
|
|
17308
|
+
destination,
|
|
17309
|
+
// For now, the fee asset is always the one used for the protocol fee
|
|
17310
|
+
// If it where to change, we need make protocolFee a FeeConfig in MrlSourceConfig
|
|
17311
|
+
asset: feeAsset,
|
|
17312
|
+
balance,
|
|
17313
|
+
protocolFee: route.source.protocolFee,
|
|
17314
|
+
address: destinationAddress
|
|
17315
|
+
});
|
|
17135
17316
|
const transfer = await buildTransfer({
|
|
17136
|
-
asset: balance,
|
|
17317
|
+
asset: balance.copyWith({ amount: balance.amount - protocolFee.amount }),
|
|
17318
|
+
protocolFee,
|
|
17137
17319
|
destinationAddress,
|
|
17138
17320
|
feeAsset: feeBalance,
|
|
17139
17321
|
isAutomatic,
|
|
@@ -17170,13 +17352,16 @@ async function getSourceData({
|
|
|
17170
17352
|
chain: source,
|
|
17171
17353
|
destinationFee,
|
|
17172
17354
|
destinationFeeBalance,
|
|
17173
|
-
|
|
17355
|
+
bridgeChainFeeBalance,
|
|
17174
17356
|
existentialDeposit,
|
|
17175
17357
|
fee,
|
|
17176
17358
|
feeBalance,
|
|
17177
17359
|
max,
|
|
17178
17360
|
min,
|
|
17179
|
-
|
|
17361
|
+
otherFees: {
|
|
17362
|
+
protocol: protocolFee,
|
|
17363
|
+
relayer: relayerFee?.amount ? relayerFee : void 0
|
|
17364
|
+
}
|
|
17180
17365
|
};
|
|
17181
17366
|
}
|
|
17182
17367
|
async function getFee({
|
|
@@ -17193,17 +17378,29 @@ async function getFee({
|
|
|
17193
17378
|
amount: 0n
|
|
17194
17379
|
});
|
|
17195
17380
|
}
|
|
17196
|
-
if (
|
|
17197
|
-
|
|
17198
|
-
|
|
17199
|
-
|
|
17200
|
-
|
|
17201
|
-
contract: transfer,
|
|
17202
|
-
destinationFee,
|
|
17203
|
-
feeBalance,
|
|
17204
|
-
feeConfig
|
|
17381
|
+
if (SnowbridgeConfig.is(transfer)) {
|
|
17382
|
+
const snowbridge = SnowbridgeService.create(chain2);
|
|
17383
|
+
const feeAmount = await snowbridge.getFee(sourceAddress, transfer);
|
|
17384
|
+
return AssetAmount2.fromChainAsset(chain2.getChainAsset(feeBalance), {
|
|
17385
|
+
amount: feeAmount
|
|
17205
17386
|
});
|
|
17206
17387
|
}
|
|
17388
|
+
if (ContractConfig2.is(transfer)) {
|
|
17389
|
+
try {
|
|
17390
|
+
return getContractFee({
|
|
17391
|
+
address: sourceAddress,
|
|
17392
|
+
balance,
|
|
17393
|
+
chain: chain2,
|
|
17394
|
+
contract: transfer,
|
|
17395
|
+
destinationFee,
|
|
17396
|
+
feeBalance,
|
|
17397
|
+
feeConfig
|
|
17398
|
+
});
|
|
17399
|
+
} catch (error) {
|
|
17400
|
+
console.error(error);
|
|
17401
|
+
return feeBalance.copyWith({ amount: 0n });
|
|
17402
|
+
}
|
|
17403
|
+
}
|
|
17207
17404
|
return getExtrinsicFee({
|
|
17208
17405
|
address: sourceAddress,
|
|
17209
17406
|
balance,
|
|
@@ -17223,19 +17420,25 @@ async function getRelayerFee({
|
|
|
17223
17420
|
sourceAddress,
|
|
17224
17421
|
transfer
|
|
17225
17422
|
}) {
|
|
17423
|
+
if (route.mrl.transfer.provider === Provider2.Snowbridge || SnowbridgeConfig.is(transfer)) {
|
|
17424
|
+
return void 0;
|
|
17425
|
+
}
|
|
17226
17426
|
if (WormholeConfig.is(transfer)) {
|
|
17227
17427
|
return getWormholeFee({ asset, chain: chain2, config: transfer });
|
|
17228
17428
|
}
|
|
17229
|
-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
17236
|
-
|
|
17237
|
-
|
|
17238
|
-
|
|
17429
|
+
if (route.mrl.transfer.provider === Provider2.Wormhole) {
|
|
17430
|
+
const builderParams = await getMrlBuilderParams({
|
|
17431
|
+
asset,
|
|
17432
|
+
destinationAddress,
|
|
17433
|
+
feeAsset,
|
|
17434
|
+
isAutomatic,
|
|
17435
|
+
route,
|
|
17436
|
+
sourceAddress
|
|
17437
|
+
});
|
|
17438
|
+
const wormholeConfig = MrlBuilder3().wormhole().wormhole().tokenTransfer().build(builderParams);
|
|
17439
|
+
return getWormholeFee({ asset, chain: chain2, config: wormholeConfig });
|
|
17440
|
+
}
|
|
17441
|
+
return;
|
|
17239
17442
|
}
|
|
17240
17443
|
async function getWormholeFee({
|
|
17241
17444
|
asset,
|
|
@@ -17252,33 +17455,76 @@ async function getWormholeFee({
|
|
|
17252
17455
|
}
|
|
17253
17456
|
return;
|
|
17254
17457
|
}
|
|
17255
|
-
async function
|
|
17458
|
+
async function getBridgeChainFeeBalance({
|
|
17256
17459
|
balance,
|
|
17257
17460
|
feeBalance,
|
|
17258
17461
|
route,
|
|
17259
17462
|
sourceAddress
|
|
17260
17463
|
}) {
|
|
17261
|
-
if (!route.source.
|
|
17464
|
+
if (!route.source.bridgeChainFee) {
|
|
17262
17465
|
return void 0;
|
|
17263
17466
|
}
|
|
17264
|
-
if (route.mrl?.
|
|
17467
|
+
if (route.mrl?.bridgeChain.fee.asset.isEqual(balance)) {
|
|
17265
17468
|
return balance;
|
|
17266
17469
|
}
|
|
17267
|
-
if (route.mrl?.
|
|
17470
|
+
if (route.mrl?.bridgeChain.fee.asset.isEqual(feeBalance)) {
|
|
17268
17471
|
return feeBalance;
|
|
17269
17472
|
}
|
|
17270
|
-
if (!route.source.
|
|
17473
|
+
if (!route.source.bridgeChainFee.balance) {
|
|
17271
17474
|
throw new Error(
|
|
17272
|
-
"BalanceBuilder must be defined for source.
|
|
17475
|
+
"BalanceBuilder must be defined for source.bridgeChainFee.balance for MrlAssetRoute"
|
|
17273
17476
|
);
|
|
17274
17477
|
}
|
|
17275
17478
|
return getBalance2({
|
|
17276
17479
|
address: sourceAddress,
|
|
17277
|
-
asset: route.source.chain.getChainAsset(route.source.
|
|
17278
|
-
builder: route.source.
|
|
17480
|
+
asset: route.source.chain.getChainAsset(route.source.bridgeChainFee.asset),
|
|
17481
|
+
builder: route.source.bridgeChainFee.balance,
|
|
17279
17482
|
chain: route.source.chain
|
|
17280
17483
|
});
|
|
17281
17484
|
}
|
|
17485
|
+
async function getProtocolFee({
|
|
17486
|
+
address,
|
|
17487
|
+
asset,
|
|
17488
|
+
balance,
|
|
17489
|
+
protocolFee,
|
|
17490
|
+
destination,
|
|
17491
|
+
source
|
|
17492
|
+
}) {
|
|
17493
|
+
if (typeof protocolFee === "number") {
|
|
17494
|
+
return AssetAmount2.fromChainAsset(asset, {
|
|
17495
|
+
amount: protocolFee
|
|
17496
|
+
});
|
|
17497
|
+
}
|
|
17498
|
+
const config = protocolFee?.build({
|
|
17499
|
+
address,
|
|
17500
|
+
asset,
|
|
17501
|
+
balance,
|
|
17502
|
+
destination,
|
|
17503
|
+
source
|
|
17504
|
+
});
|
|
17505
|
+
if (ContractConfig2.is(config) && EvmChain2.is(source)) {
|
|
17506
|
+
const evm = EvmService3.create(source);
|
|
17507
|
+
const amount = await evm.read(config);
|
|
17508
|
+
if (typeof amount !== "bigint") {
|
|
17509
|
+
throw new Error(
|
|
17510
|
+
`Error getting bridge fee: expected bigint from contract call, but received ${typeof amount}. `
|
|
17511
|
+
);
|
|
17512
|
+
}
|
|
17513
|
+
return AssetAmount2.fromChainAsset(asset, {
|
|
17514
|
+
amount
|
|
17515
|
+
});
|
|
17516
|
+
}
|
|
17517
|
+
if (SubstrateQueryConfig.is(config) && EvmParachain3.isAnyParachain(source)) {
|
|
17518
|
+
const polkadot = await PolkadotService2.create(source);
|
|
17519
|
+
const amount = await polkadot.query(config);
|
|
17520
|
+
return AssetAmount2.fromChainAsset(asset, {
|
|
17521
|
+
amount
|
|
17522
|
+
});
|
|
17523
|
+
}
|
|
17524
|
+
return AssetAmount2.fromChainAsset(source.getChainAsset(asset), {
|
|
17525
|
+
amount: 0n
|
|
17526
|
+
});
|
|
17527
|
+
}
|
|
17282
17528
|
|
|
17283
17529
|
// src/getTransferData/getTransferData.ts
|
|
17284
17530
|
async function getTransferData({
|
|
@@ -17307,7 +17553,7 @@ async function getTransferData({
|
|
|
17307
17553
|
destinationFee,
|
|
17308
17554
|
sourceAddress
|
|
17309
17555
|
});
|
|
17310
|
-
const
|
|
17556
|
+
const bridgeChainData = await getBridgeChainData({
|
|
17311
17557
|
route,
|
|
17312
17558
|
sourceAddress,
|
|
17313
17559
|
destinationAddress
|
|
@@ -17319,14 +17565,14 @@ async function getTransferData({
|
|
|
17319
17565
|
const bigAmount = Big2(
|
|
17320
17566
|
toBigInt3(amount, sourceData.balance.decimals).toString()
|
|
17321
17567
|
);
|
|
17322
|
-
const fee =
|
|
17568
|
+
const fee = getBridgeChainFeeValueOnSource({
|
|
17323
17569
|
destinationData,
|
|
17324
|
-
|
|
17570
|
+
bridgeChainData,
|
|
17325
17571
|
sourceData
|
|
17326
17572
|
});
|
|
17327
17573
|
const result = bigAmount.minus(
|
|
17328
17574
|
isSameAssetPayingDestinationFee ? destinationFee.toBig() : Big2(0)
|
|
17329
|
-
).minus(fee).minus(sourceData.
|
|
17575
|
+
).minus(fee).minus(sourceData.otherFees?.relayer?.toBig() || Big2(0));
|
|
17330
17576
|
return sourceData.balance.copyWith({
|
|
17331
17577
|
amount: result.lt(0) ? 0n : BigInt(result.toFixed())
|
|
17332
17578
|
});
|
|
@@ -17335,10 +17581,10 @@ async function getTransferData({
|
|
|
17335
17581
|
max: sourceData.max,
|
|
17336
17582
|
min: getMrlMin({
|
|
17337
17583
|
destinationData,
|
|
17338
|
-
|
|
17584
|
+
bridgeChainData,
|
|
17339
17585
|
sourceData
|
|
17340
17586
|
}),
|
|
17341
|
-
|
|
17587
|
+
bridgeChain: bridgeChainData,
|
|
17342
17588
|
source: sourceData,
|
|
17343
17589
|
async transfer({
|
|
17344
17590
|
amount,
|
|
@@ -17361,6 +17607,7 @@ async function getTransferData({
|
|
|
17361
17607
|
);
|
|
17362
17608
|
const transfer = await buildTransfer({
|
|
17363
17609
|
asset,
|
|
17610
|
+
protocolFee: sourceData.otherFees?.protocol,
|
|
17364
17611
|
destinationAddress,
|
|
17365
17612
|
feeAsset,
|
|
17366
17613
|
isAutomatic: isAutomatic2,
|
|
@@ -17368,19 +17615,19 @@ async function getTransferData({
|
|
|
17368
17615
|
sendOnlyRemoteExecution,
|
|
17369
17616
|
sourceAddress
|
|
17370
17617
|
});
|
|
17371
|
-
if (
|
|
17618
|
+
if (ContractConfig3.is(transfer) && (EvmChain3.is(source) || EvmParachain4.is(source))) {
|
|
17372
17619
|
if (!evmSigner) {
|
|
17373
17620
|
throw new Error("EVM Signer must be provided");
|
|
17374
17621
|
}
|
|
17375
|
-
const evm =
|
|
17622
|
+
const evm = EvmService4.create(source);
|
|
17376
17623
|
const hash = await evm.transfer(evmSigner, transfer);
|
|
17377
17624
|
return [hash];
|
|
17378
17625
|
}
|
|
17379
|
-
if (ExtrinsicConfig.is(transfer) &&
|
|
17626
|
+
if (ExtrinsicConfig.is(transfer) && EvmParachain4.isAnyParachain(source)) {
|
|
17380
17627
|
if (!polkadotSigner) {
|
|
17381
17628
|
throw new Error("Polkadot signer must be provided");
|
|
17382
17629
|
}
|
|
17383
|
-
const polkadot = await
|
|
17630
|
+
const polkadot = await PolkadotService3.create(source);
|
|
17384
17631
|
const hash = await polkadot.transfer(
|
|
17385
17632
|
sourceAddress,
|
|
17386
17633
|
transfer,
|
|
@@ -17389,13 +17636,21 @@ async function getTransferData({
|
|
|
17389
17636
|
);
|
|
17390
17637
|
return [hash];
|
|
17391
17638
|
}
|
|
17392
|
-
if (WormholeConfig2.is(transfer) && (
|
|
17639
|
+
if (WormholeConfig2.is(transfer) && (EvmChain3.is(source) || EvmParachain4.is(source))) {
|
|
17393
17640
|
if (!evmSigner) {
|
|
17394
17641
|
throw new Error("EVM Signer must be provided");
|
|
17395
17642
|
}
|
|
17396
17643
|
const wh = WormholeService.create(source);
|
|
17397
17644
|
return wh.transfer(evmSigner, transfer);
|
|
17398
17645
|
}
|
|
17646
|
+
if (SnowbridgeConfig2.is(transfer) && (EvmChain3.is(source) || EvmParachain4.is(source))) {
|
|
17647
|
+
if (!evmSigner) {
|
|
17648
|
+
throw new Error("EVM Signer must be provided");
|
|
17649
|
+
}
|
|
17650
|
+
const snowbridge = SnowbridgeService.create(source);
|
|
17651
|
+
const hash = await snowbridge.transfer(evmSigner, transfer);
|
|
17652
|
+
return [hash];
|
|
17653
|
+
}
|
|
17399
17654
|
throw new Error("Either contract or extrinsic must be provided");
|
|
17400
17655
|
}
|
|
17401
17656
|
};
|