@atomiqlabs/chain-evm 1.0.0-dev.35 → 1.0.0-dev.37
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/LICENSE +201 -201
- package/dist/chains/citrea/CitreaBtcRelay.d.ts +21 -21
- package/dist/chains/citrea/CitreaBtcRelay.js +43 -43
- package/dist/chains/citrea/CitreaChainType.d.ts +13 -13
- package/dist/chains/citrea/CitreaChainType.js +2 -2
- package/dist/chains/citrea/CitreaFees.d.ts +29 -29
- package/dist/chains/citrea/CitreaFees.js +67 -67
- package/dist/chains/citrea/CitreaInitializer.d.ts +30 -30
- package/dist/chains/citrea/CitreaInitializer.js +127 -127
- package/dist/chains/citrea/CitreaSpvVaultContract.d.ts +15 -15
- package/dist/chains/citrea/CitreaSpvVaultContract.js +74 -74
- package/dist/chains/citrea/CitreaSwapContract.d.ts +22 -22
- package/dist/chains/citrea/CitreaSwapContract.js +96 -96
- package/dist/chains/citrea/CitreaTokens.d.ts +9 -9
- package/dist/chains/citrea/CitreaTokens.js +20 -20
- package/dist/evm/btcrelay/BtcRelayAbi.d.ts +198 -198
- package/dist/evm/btcrelay/BtcRelayAbi.js +261 -261
- package/dist/evm/btcrelay/BtcRelayTypechain.d.ts +172 -172
- package/dist/evm/btcrelay/BtcRelayTypechain.js +2 -2
- package/dist/evm/btcrelay/EVMBtcRelay.d.ts +195 -195
- package/dist/evm/btcrelay/EVMBtcRelay.js +423 -423
- package/dist/evm/btcrelay/headers/EVMBtcHeader.d.ts +33 -33
- package/dist/evm/btcrelay/headers/EVMBtcHeader.js +84 -84
- package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.d.ts +56 -56
- package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.js +123 -123
- package/dist/evm/chain/EVMChainInterface.d.ts +51 -51
- package/dist/evm/chain/EVMChainInterface.js +89 -89
- package/dist/evm/chain/EVMModule.d.ts +9 -9
- package/dist/evm/chain/EVMModule.js +13 -13
- package/dist/evm/chain/modules/ERC20Abi.d.ts +168 -168
- package/dist/evm/chain/modules/ERC20Abi.js +225 -225
- package/dist/evm/chain/modules/EVMAddresses.d.ts +10 -10
- package/dist/evm/chain/modules/EVMAddresses.js +30 -30
- package/dist/evm/chain/modules/EVMBlocks.d.ts +20 -20
- package/dist/evm/chain/modules/EVMBlocks.js +64 -64
- package/dist/evm/chain/modules/EVMEvents.d.ts +36 -36
- package/dist/evm/chain/modules/EVMEvents.js +122 -122
- package/dist/evm/chain/modules/EVMFees.d.ts +36 -36
- package/dist/evm/chain/modules/EVMFees.js +73 -73
- package/dist/evm/chain/modules/EVMSignatures.d.ts +29 -29
- package/dist/evm/chain/modules/EVMSignatures.js +68 -68
- package/dist/evm/chain/modules/EVMTokens.d.ts +70 -51
- package/dist/evm/chain/modules/EVMTokens.js +142 -113
- package/dist/evm/chain/modules/EVMTransactions.d.ts +89 -89
- package/dist/evm/chain/modules/EVMTransactions.js +230 -216
- package/dist/evm/contract/EVMContractBase.d.ts +22 -22
- package/dist/evm/contract/EVMContractBase.js +34 -34
- package/dist/evm/contract/EVMContractModule.d.ts +8 -8
- package/dist/evm/contract/EVMContractModule.js +11 -11
- package/dist/evm/contract/modules/EVMContractEvents.d.ts +42 -42
- package/dist/evm/contract/modules/EVMContractEvents.js +75 -75
- package/dist/evm/events/EVMChainEvents.d.ts +22 -22
- package/dist/evm/events/EVMChainEvents.js +67 -67
- package/dist/evm/events/EVMChainEventsBrowser.d.ts +86 -86
- package/dist/evm/events/EVMChainEventsBrowser.js +294 -294
- package/dist/evm/spv_swap/EVMSpvVaultContract.d.ts +78 -78
- package/dist/evm/spv_swap/EVMSpvVaultContract.js +478 -480
- package/dist/evm/spv_swap/EVMSpvVaultData.d.ts +39 -39
- package/dist/evm/spv_swap/EVMSpvVaultData.js +180 -180
- package/dist/evm/spv_swap/EVMSpvWithdrawalData.d.ts +19 -19
- package/dist/evm/spv_swap/EVMSpvWithdrawalData.js +55 -55
- package/dist/evm/spv_swap/SpvVaultContractAbi.d.ts +91 -91
- package/dist/evm/spv_swap/SpvVaultContractAbi.js +849 -849
- package/dist/evm/spv_swap/SpvVaultContractTypechain.d.ts +450 -450
- package/dist/evm/spv_swap/SpvVaultContractTypechain.js +2 -2
- package/dist/evm/swaps/EVMSwapContract.d.ts +193 -193
- package/dist/evm/swaps/EVMSwapContract.js +374 -374
- package/dist/evm/swaps/EVMSwapData.d.ts +66 -66
- package/dist/evm/swaps/EVMSwapData.js +260 -260
- package/dist/evm/swaps/EVMSwapModule.d.ts +9 -9
- package/dist/evm/swaps/EVMSwapModule.js +11 -11
- package/dist/evm/swaps/EscrowManagerAbi.d.ts +120 -120
- package/dist/evm/swaps/EscrowManagerAbi.js +985 -985
- package/dist/evm/swaps/EscrowManagerTypechain.d.ts +475 -475
- package/dist/evm/swaps/EscrowManagerTypechain.js +2 -2
- package/dist/evm/swaps/handlers/IHandler.d.ts +13 -13
- package/dist/evm/swaps/handlers/IHandler.js +2 -2
- package/dist/evm/swaps/handlers/claim/ClaimHandlers.d.ts +10 -10
- package/dist/evm/swaps/handlers/claim/ClaimHandlers.js +13 -13
- package/dist/evm/swaps/handlers/claim/HashlockClaimHandler.d.ts +20 -20
- package/dist/evm/swaps/handlers/claim/HashlockClaimHandler.js +39 -39
- package/dist/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +24 -24
- package/dist/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.js +59 -59
- package/dist/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +25 -25
- package/dist/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.js +51 -51
- package/dist/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +21 -21
- package/dist/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.js +28 -28
- package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +48 -48
- package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +63 -63
- package/dist/evm/swaps/handlers/refund/TimelockRefundHandler.d.ts +17 -17
- package/dist/evm/swaps/handlers/refund/TimelockRefundHandler.js +28 -28
- package/dist/evm/swaps/modules/EVMLpVault.d.ts +69 -69
- package/dist/evm/swaps/modules/EVMLpVault.js +134 -131
- package/dist/evm/swaps/modules/EVMSwapClaim.d.ts +54 -54
- package/dist/evm/swaps/modules/EVMSwapClaim.js +137 -137
- package/dist/evm/swaps/modules/EVMSwapInit.d.ts +88 -88
- package/dist/evm/swaps/modules/EVMSwapInit.js +274 -275
- package/dist/evm/swaps/modules/EVMSwapRefund.d.ts +62 -62
- package/dist/evm/swaps/modules/EVMSwapRefund.js +167 -167
- package/dist/evm/typechain/common.d.ts +50 -50
- package/dist/evm/typechain/common.js +2 -2
- package/dist/evm/wallet/EVMSigner.d.ts +10 -9
- package/dist/evm/wallet/EVMSigner.js +17 -16
- package/dist/index.d.ts +38 -38
- package/dist/index.js +54 -54
- package/dist/utils/Utils.d.ts +15 -15
- package/dist/utils/Utils.js +71 -71
- package/package.json +37 -37
- package/src/chains/citrea/CitreaBtcRelay.ts +57 -57
- package/src/chains/citrea/CitreaChainType.ts +28 -28
- package/src/chains/citrea/CitreaFees.ts +77 -77
- package/src/chains/citrea/CitreaInitializer.ts +178 -178
- package/src/chains/citrea/CitreaSpvVaultContract.ts +75 -75
- package/src/chains/citrea/CitreaSwapContract.ts +102 -102
- package/src/chains/citrea/CitreaTokens.ts +21 -21
- package/src/evm/btcrelay/BtcRelayAbi.ts +258 -258
- package/src/evm/btcrelay/BtcRelayTypechain.ts +371 -371
- package/src/evm/btcrelay/EVMBtcRelay.ts +522 -522
- package/src/evm/btcrelay/headers/EVMBtcHeader.ts +109 -109
- package/src/evm/btcrelay/headers/EVMBtcStoredHeader.ts +152 -152
- package/src/evm/chain/EVMChainInterface.ts +155 -155
- package/src/evm/chain/EVMModule.ts +21 -21
- package/src/evm/chain/modules/ERC20Abi.ts +222 -222
- package/src/evm/chain/modules/EVMAddresses.ts +28 -28
- package/src/evm/chain/modules/EVMBlocks.ts +75 -75
- package/src/evm/chain/modules/EVMEvents.ts +139 -139
- package/src/evm/chain/modules/EVMFees.ts +104 -104
- package/src/evm/chain/modules/EVMSignatures.ts +76 -76
- package/src/evm/chain/modules/EVMTokens.ts +155 -126
- package/src/evm/chain/modules/EVMTransactions.ts +257 -246
- package/src/evm/contract/EVMContractBase.ts +63 -63
- package/src/evm/contract/EVMContractModule.ts +16 -16
- package/src/evm/contract/modules/EVMContractEvents.ts +102 -102
- package/src/evm/events/EVMChainEvents.ts +81 -81
- package/src/evm/events/EVMChainEventsBrowser.ts +390 -390
- package/src/evm/spv_swap/EVMSpvVaultContract.ts +608 -603
- package/src/evm/spv_swap/EVMSpvVaultData.ts +224 -224
- package/src/evm/spv_swap/EVMSpvWithdrawalData.ts +70 -70
- package/src/evm/spv_swap/SpvVaultContractAbi.ts +846 -846
- package/src/evm/spv_swap/SpvVaultContractTypechain.ts +685 -685
- package/src/evm/swaps/EVMSwapContract.ts +592 -592
- package/src/evm/swaps/EVMSwapData.ts +378 -378
- package/src/evm/swaps/EVMSwapModule.ts +16 -16
- package/src/evm/swaps/EscrowManagerAbi.ts +982 -982
- package/src/evm/swaps/EscrowManagerTypechain.ts +723 -723
- package/src/evm/swaps/handlers/IHandler.ts +17 -17
- package/src/evm/swaps/handlers/claim/ClaimHandlers.ts +20 -20
- package/src/evm/swaps/handlers/claim/HashlockClaimHandler.ts +46 -46
- package/src/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +82 -82
- package/src/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +76 -76
- package/src/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +46 -46
- package/src/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +115 -115
- package/src/evm/swaps/handlers/refund/TimelockRefundHandler.ts +37 -37
- package/src/evm/swaps/modules/EVMLpVault.ts +154 -152
- package/src/evm/swaps/modules/EVMSwapClaim.ts +172 -172
- package/src/evm/swaps/modules/EVMSwapInit.ts +328 -325
- package/src/evm/swaps/modules/EVMSwapRefund.ts +229 -229
- package/src/evm/typechain/common.ts +131 -131
- package/src/evm/wallet/EVMSigner.ts +25 -23
- package/src/index.ts +45 -45
- package/src/utils/Utils.ts +81 -81
|
@@ -1,326 +1,329 @@
|
|
|
1
|
-
import {SignatureVerificationError, SwapCommitStateType, SwapDataVerificationError} from "@atomiqlabs/base";
|
|
2
|
-
import { EVMSwapModule } from "../EVMSwapModule";
|
|
3
|
-
import {EVMSwapData} from "../EVMSwapData";
|
|
4
|
-
import {keccak256, TransactionRequest, ZeroHash} from "ethers";
|
|
5
|
-
import {EVMFees} from "../../chain/modules/EVMFees";
|
|
6
|
-
import {EVMSigner} from "../../wallet/EVMSigner";
|
|
7
|
-
import {EVMTx} from "../../chain/modules/EVMTransactions";
|
|
8
|
-
import {tryWithRetries} from "../../../utils/Utils";
|
|
9
|
-
|
|
10
|
-
export type EVMPreFetchVerification = {
|
|
11
|
-
safeBlockTime?: number
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const Initialize = [
|
|
15
|
-
{ name: "swapHash", type: "bytes32" },
|
|
16
|
-
{ name: "offerer", type: "address" },
|
|
17
|
-
{ name: "claimer", type: "address" },
|
|
18
|
-
{ name: "amount", type: "uint256" },
|
|
19
|
-
{ name: "token", type: "address" },
|
|
20
|
-
{ name: "payIn", type: "bool" },
|
|
21
|
-
{ name: "payOut", type: "bool" },
|
|
22
|
-
{ name: "trackingReputation", type: "bool" },
|
|
23
|
-
{ name: "claimHandler", type: "address" },
|
|
24
|
-
{ name: "claimData", type: "bytes32" },
|
|
25
|
-
{ name: "refundHandler", type: "address" },
|
|
26
|
-
{ name: "refundData", type: "bytes32" },
|
|
27
|
-
{ name: "securityDeposit", type: "uint256" },
|
|
28
|
-
{ name: "claimerBounty", type: "uint256" },
|
|
29
|
-
{ name: "depositToken", type: "address" },
|
|
30
|
-
{ name: "claimActionHash", type: "bytes32" },
|
|
31
|
-
{ name: "deadline", type: "uint256" },
|
|
32
|
-
{ name: "extraDataHash", type: "bytes32" }
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
export class EVMSwapInit extends EVMSwapModule {
|
|
36
|
-
|
|
37
|
-
private static readonly GasCosts = {
|
|
38
|
-
BASE: 45_000 + 21_000,
|
|
39
|
-
ERC20_TRANSFER: 40_000,
|
|
40
|
-
LP_VAULT_TRANSFER: 10_000
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* bare Init action based on the data passed in swapData
|
|
45
|
-
*
|
|
46
|
-
* @param sender
|
|
47
|
-
* @param swapData
|
|
48
|
-
* @param timeout
|
|
49
|
-
* @param signature
|
|
50
|
-
* @param feeRate
|
|
51
|
-
* @private
|
|
52
|
-
*/
|
|
53
|
-
private async Init(sender: string, swapData: EVMSwapData, timeout: bigint, signature: string, feeRate: string): Promise<TransactionRequest> {
|
|
54
|
-
let value = 0n;
|
|
55
|
-
if(swapData.isPayIn()) {
|
|
56
|
-
if(swapData.isOfferer(sender) && swapData.isToken(this.root.getNativeCurrencyAddress())) value += swapData.getAmount();
|
|
57
|
-
}
|
|
58
|
-
if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) value += swapData.getTotalDeposit();
|
|
59
|
-
const tx = await this.swapContract.initialize.populateTransaction(swapData.toEscrowStruct(), signature, timeout, "0x"+(swapData.extraData ?? ""), {
|
|
60
|
-
value
|
|
61
|
-
});
|
|
62
|
-
tx.from = sender;
|
|
63
|
-
EVMFees.applyFeeRate(tx, this.getInitGas(swapData), feeRate);
|
|
64
|
-
return tx;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Returns auth prefix to be used with a specific swap, payIn=true & payIn=false use different prefixes (these
|
|
69
|
-
* actually have no meaning for the smart contract in the EVM case)
|
|
70
|
-
*
|
|
71
|
-
* @param swapData
|
|
72
|
-
* @private
|
|
73
|
-
*/
|
|
74
|
-
private getAuthPrefix(swapData: EVMSwapData): string {
|
|
75
|
-
return swapData.isPayIn() ? "claim_initialize" : "initialize";
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
public async preFetchForInitSignatureVerification(): Promise<EVMPreFetchVerification> {
|
|
79
|
-
return {
|
|
80
|
-
safeBlockTime: await this.root.Blocks.getBlockTime(this.root.config.safeBlockTag)
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Signs swap initialization authorization, using data from preFetchedBlockData if provided & still valid (subject
|
|
86
|
-
* to SIGNATURE_PREFETCH_DATA_VALIDITY)
|
|
87
|
-
*
|
|
88
|
-
* @param signer
|
|
89
|
-
* @param swapData
|
|
90
|
-
* @param authorizationTimeout
|
|
91
|
-
* @public
|
|
92
|
-
*/
|
|
93
|
-
public async signSwapInitialization(
|
|
94
|
-
signer: EVMSigner,
|
|
95
|
-
swapData: EVMSwapData,
|
|
96
|
-
authorizationTimeout: number
|
|
97
|
-
): Promise<{prefix: string, timeout: string, signature: string}> {
|
|
98
|
-
const authExpiry = Math.floor(Date.now()/1000)+authorizationTimeout;
|
|
99
|
-
|
|
100
|
-
const signature = await this.root.Signatures.signTypedMessage(this.contract.contractAddress, signer, Initialize, "Initialize", {
|
|
101
|
-
"swapHash": "0x"+swapData.getEscrowHash(),
|
|
102
|
-
"offerer": swapData.offerer,
|
|
103
|
-
"claimer": swapData.claimer,
|
|
104
|
-
"amount": swapData.amount,
|
|
105
|
-
"token": swapData.token,
|
|
106
|
-
"payIn": swapData.isPayIn(),
|
|
107
|
-
"payOut": swapData.isPayOut(),
|
|
108
|
-
"trackingReputation": swapData.reputation,
|
|
109
|
-
"claimHandler": swapData.claimHandler,
|
|
110
|
-
"claimData": "0x"+swapData.getClaimHash(),
|
|
111
|
-
"refundHandler": swapData.refundHandler,
|
|
112
|
-
"refundData": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
|
|
113
|
-
"securityDeposit": swapData.securityDeposit,
|
|
114
|
-
"claimerBounty": swapData.claimerBounty,
|
|
115
|
-
"depositToken": swapData.depositToken,
|
|
116
|
-
"claimActionHash": ZeroHash,
|
|
117
|
-
"deadline": authExpiry,
|
|
118
|
-
"extraDataHash": keccak256("0x"+(swapData.extraData ?? ""))
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
prefix: this.getAuthPrefix(swapData),
|
|
123
|
-
timeout: authExpiry.toString(10),
|
|
124
|
-
signature
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Checks whether the provided signature data is valid, using preFetchedData if provided and still valid
|
|
130
|
-
*
|
|
131
|
-
* @param sender
|
|
132
|
-
* @param swapData
|
|
133
|
-
* @param timeout
|
|
134
|
-
* @param prefix
|
|
135
|
-
* @param signature
|
|
136
|
-
* @param preFetchData
|
|
137
|
-
* @public
|
|
138
|
-
*/
|
|
139
|
-
public async isSignatureValid(
|
|
140
|
-
sender: string,
|
|
141
|
-
swapData: EVMSwapData,
|
|
142
|
-
timeout: string,
|
|
143
|
-
prefix: string,
|
|
144
|
-
signature: string,
|
|
145
|
-
preFetchData?: EVMPreFetchVerification
|
|
146
|
-
): Promise<null> {
|
|
147
|
-
if(!swapData.isOfferer(sender) && !swapData.isClaimer(sender))
|
|
148
|
-
throw new SignatureVerificationError("TX sender not offerer nor claimer");
|
|
149
|
-
|
|
150
|
-
const signer = swapData.isOfferer(sender) ? swapData.claimer : swapData.offerer;
|
|
151
|
-
|
|
152
|
-
if(await this.contract.isExpired(sender, swapData)) {
|
|
153
|
-
throw new SignatureVerificationError("Swap will expire too soon!");
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if(prefix!==this.getAuthPrefix(swapData)) throw new SignatureVerificationError("Invalid prefix");
|
|
157
|
-
|
|
158
|
-
const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
159
|
-
const timeoutBN = BigInt(timeout);
|
|
160
|
-
const isExpired = (timeoutBN - currentTimestamp) < BigInt(this.contract.authGracePeriod);
|
|
161
|
-
if (isExpired) throw new SignatureVerificationError("Authorization expired!");
|
|
162
|
-
if(await this.isSignatureExpired(timeout, preFetchData)) throw new SignatureVerificationError("Authorization expired!");
|
|
163
|
-
|
|
164
|
-
const valid = await this.root.Signatures.isValidSignature(this.contract.contractAddress, signature, signer, Initialize, "Initialize", {
|
|
165
|
-
"swapHash": "0x"+swapData.getEscrowHash(),
|
|
166
|
-
"offerer": swapData.offerer,
|
|
167
|
-
"claimer": swapData.claimer,
|
|
168
|
-
"amount": swapData.amount,
|
|
169
|
-
"token": swapData.token,
|
|
170
|
-
"payIn": swapData.isPayIn(),
|
|
171
|
-
"payOut": swapData.isPayOut(),
|
|
172
|
-
"trackingReputation": swapData.reputation,
|
|
173
|
-
"claimHandler": swapData.claimHandler,
|
|
174
|
-
"claimData": "0x"+swapData.getClaimHash(),
|
|
175
|
-
"refundHandler": swapData.refundHandler,
|
|
176
|
-
"refundData": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
|
|
177
|
-
"securityDeposit": swapData.securityDeposit,
|
|
178
|
-
"claimerBounty": swapData.claimerBounty,
|
|
179
|
-
"depositToken": swapData.depositToken,
|
|
180
|
-
"claimActionHash": ZeroHash,
|
|
181
|
-
"deadline": timeoutBN,
|
|
182
|
-
"extraDataHash": keccak256("0x"+(swapData.extraData ?? ""))
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
if(!valid) throw new SignatureVerificationError("Invalid signature!");
|
|
186
|
-
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Gets expiry of the provided signature data, this is a minimum of slot expiry & swap signature expiry
|
|
192
|
-
*
|
|
193
|
-
* @param timeout
|
|
194
|
-
* @public
|
|
195
|
-
*/
|
|
196
|
-
public async getSignatureExpiry(
|
|
197
|
-
timeout: string
|
|
198
|
-
): Promise<number> {
|
|
199
|
-
const now = Date.now();
|
|
200
|
-
const timeoutExpiryTime = (parseInt(timeout)-this.contract.authGracePeriod)*1000;
|
|
201
|
-
|
|
202
|
-
if(timeoutExpiryTime<now) return 0;
|
|
203
|
-
|
|
204
|
-
return timeoutExpiryTime;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
|
|
209
|
-
*
|
|
210
|
-
* @param timeout
|
|
211
|
-
* @param preFetchData
|
|
212
|
-
* @public
|
|
213
|
-
*/
|
|
214
|
-
public async isSignatureExpired(
|
|
215
|
-
timeout: string,
|
|
216
|
-
preFetchData?: EVMPreFetchVerification
|
|
217
|
-
): Promise<boolean> {
|
|
218
|
-
if(preFetchData==null || preFetchData.safeBlockTime==null) {
|
|
219
|
-
preFetchData = await this.preFetchForInitSignatureVerification();
|
|
220
|
-
}
|
|
221
|
-
return preFetchData.safeBlockTime > parseInt(timeout);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Creates init transaction with a valid signature from an LP
|
|
226
|
-
*
|
|
227
|
-
* @param sender
|
|
228
|
-
* @param swapData swap to initialize
|
|
229
|
-
* @param timeout init signature timeout
|
|
230
|
-
* @param prefix init signature prefix
|
|
231
|
-
* @param signature init signature
|
|
232
|
-
* @param skipChecks whether to skip signature validity checks
|
|
233
|
-
* @param feeRate fee rate to use for the transaction
|
|
234
|
-
*/
|
|
235
|
-
public async txsInit(
|
|
236
|
-
sender: string,
|
|
237
|
-
swapData: EVMSwapData,
|
|
238
|
-
timeout: string,
|
|
239
|
-
prefix: string,
|
|
240
|
-
signature: string,
|
|
241
|
-
skipChecks?: boolean,
|
|
242
|
-
feeRate?: string
|
|
243
|
-
): Promise<EVMTx[]> {
|
|
244
|
-
if(
|
|
245
|
-
swapData.isClaimer(sender) && swapData.isPayIn() &&
|
|
246
|
-
swapData.isToken(this.root.getNativeCurrencyAddress())
|
|
247
|
-
) throw new Error("Cannot initialize as claimer for payIn=true and native currency!");
|
|
248
|
-
|
|
249
|
-
if(!skipChecks) {
|
|
250
|
-
const [_, payStatus] = await Promise.all([
|
|
251
|
-
swapData.isOfferer(sender) && !swapData.reputation ? Promise.resolve() : tryWithRetries(
|
|
252
|
-
() => this.isSignatureValid(sender, swapData, timeout, prefix, signature),
|
|
253
|
-
this.retryPolicy, (e) => e instanceof SignatureVerificationError
|
|
254
|
-
),
|
|
255
|
-
tryWithRetries(() => this.contract.getCommitStatus(sender, swapData), this.retryPolicy)
|
|
256
|
-
]);
|
|
257
|
-
if(payStatus.type!==SwapCommitStateType.NOT_COMMITED) throw new SwapDataVerificationError("Invoice already being paid for or paid");
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
feeRate ??= await this.root.Fees.getFeeRate();
|
|
261
|
-
|
|
262
|
-
const txs: EVMTx[] = [];
|
|
263
|
-
const requiredApprovals: {[address: string]: bigint} = {};
|
|
264
|
-
if(swapData.isPayIn() && swapData.isOfferer(sender)) {
|
|
265
|
-
if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
|
|
266
|
-
requiredApprovals[swapData.token.toLowerCase()] = swapData.amount;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if(swapData.getTotalDeposit() !== 0n) {
|
|
270
|
-
if(!swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
|
|
271
|
-
requiredApprovals[swapData.depositToken.toLowerCase()] ??= 0n;
|
|
272
|
-
requiredApprovals[swapData.depositToken.toLowerCase()] += swapData.getTotalDeposit();
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
1
|
+
import {SignatureVerificationError, SwapCommitStateType, SwapDataVerificationError} from "@atomiqlabs/base";
|
|
2
|
+
import { EVMSwapModule } from "../EVMSwapModule";
|
|
3
|
+
import {EVMSwapData} from "../EVMSwapData";
|
|
4
|
+
import {keccak256, TransactionRequest, ZeroHash} from "ethers";
|
|
5
|
+
import {EVMFees} from "../../chain/modules/EVMFees";
|
|
6
|
+
import {EVMSigner} from "../../wallet/EVMSigner";
|
|
7
|
+
import {EVMTx} from "../../chain/modules/EVMTransactions";
|
|
8
|
+
import {tryWithRetries} from "../../../utils/Utils";
|
|
9
|
+
|
|
10
|
+
export type EVMPreFetchVerification = {
|
|
11
|
+
safeBlockTime?: number
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const Initialize = [
|
|
15
|
+
{ name: "swapHash", type: "bytes32" },
|
|
16
|
+
{ name: "offerer", type: "address" },
|
|
17
|
+
{ name: "claimer", type: "address" },
|
|
18
|
+
{ name: "amount", type: "uint256" },
|
|
19
|
+
{ name: "token", type: "address" },
|
|
20
|
+
{ name: "payIn", type: "bool" },
|
|
21
|
+
{ name: "payOut", type: "bool" },
|
|
22
|
+
{ name: "trackingReputation", type: "bool" },
|
|
23
|
+
{ name: "claimHandler", type: "address" },
|
|
24
|
+
{ name: "claimData", type: "bytes32" },
|
|
25
|
+
{ name: "refundHandler", type: "address" },
|
|
26
|
+
{ name: "refundData", type: "bytes32" },
|
|
27
|
+
{ name: "securityDeposit", type: "uint256" },
|
|
28
|
+
{ name: "claimerBounty", type: "uint256" },
|
|
29
|
+
{ name: "depositToken", type: "address" },
|
|
30
|
+
{ name: "claimActionHash", type: "bytes32" },
|
|
31
|
+
{ name: "deadline", type: "uint256" },
|
|
32
|
+
{ name: "extraDataHash", type: "bytes32" }
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
export class EVMSwapInit extends EVMSwapModule {
|
|
36
|
+
|
|
37
|
+
private static readonly GasCosts = {
|
|
38
|
+
BASE: 45_000 + 21_000,
|
|
39
|
+
ERC20_TRANSFER: 40_000,
|
|
40
|
+
LP_VAULT_TRANSFER: 10_000
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* bare Init action based on the data passed in swapData
|
|
45
|
+
*
|
|
46
|
+
* @param sender
|
|
47
|
+
* @param swapData
|
|
48
|
+
* @param timeout
|
|
49
|
+
* @param signature
|
|
50
|
+
* @param feeRate
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
private async Init(sender: string, swapData: EVMSwapData, timeout: bigint, signature: string, feeRate: string): Promise<TransactionRequest> {
|
|
54
|
+
let value = 0n;
|
|
55
|
+
if(swapData.isPayIn()) {
|
|
56
|
+
if(swapData.isOfferer(sender) && swapData.isToken(this.root.getNativeCurrencyAddress())) value += swapData.getAmount();
|
|
57
|
+
}
|
|
58
|
+
if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) value += swapData.getTotalDeposit();
|
|
59
|
+
const tx = await this.swapContract.initialize.populateTransaction(swapData.toEscrowStruct(), signature, timeout, "0x"+(swapData.extraData ?? ""), {
|
|
60
|
+
value
|
|
61
|
+
});
|
|
62
|
+
tx.from = sender;
|
|
63
|
+
EVMFees.applyFeeRate(tx, this.getInitGas(swapData), feeRate);
|
|
64
|
+
return tx;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns auth prefix to be used with a specific swap, payIn=true & payIn=false use different prefixes (these
|
|
69
|
+
* actually have no meaning for the smart contract in the EVM case)
|
|
70
|
+
*
|
|
71
|
+
* @param swapData
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
private getAuthPrefix(swapData: EVMSwapData): string {
|
|
75
|
+
return swapData.isPayIn() ? "claim_initialize" : "initialize";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public async preFetchForInitSignatureVerification(): Promise<EVMPreFetchVerification> {
|
|
79
|
+
return {
|
|
80
|
+
safeBlockTime: await this.root.Blocks.getBlockTime(this.root.config.safeBlockTag)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Signs swap initialization authorization, using data from preFetchedBlockData if provided & still valid (subject
|
|
86
|
+
* to SIGNATURE_PREFETCH_DATA_VALIDITY)
|
|
87
|
+
*
|
|
88
|
+
* @param signer
|
|
89
|
+
* @param swapData
|
|
90
|
+
* @param authorizationTimeout
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
public async signSwapInitialization(
|
|
94
|
+
signer: EVMSigner,
|
|
95
|
+
swapData: EVMSwapData,
|
|
96
|
+
authorizationTimeout: number
|
|
97
|
+
): Promise<{prefix: string, timeout: string, signature: string}> {
|
|
98
|
+
const authExpiry = Math.floor(Date.now()/1000)+authorizationTimeout;
|
|
99
|
+
|
|
100
|
+
const signature = await this.root.Signatures.signTypedMessage(this.contract.contractAddress, signer, Initialize, "Initialize", {
|
|
101
|
+
"swapHash": "0x"+swapData.getEscrowHash(),
|
|
102
|
+
"offerer": swapData.offerer,
|
|
103
|
+
"claimer": swapData.claimer,
|
|
104
|
+
"amount": swapData.amount,
|
|
105
|
+
"token": swapData.token,
|
|
106
|
+
"payIn": swapData.isPayIn(),
|
|
107
|
+
"payOut": swapData.isPayOut(),
|
|
108
|
+
"trackingReputation": swapData.reputation,
|
|
109
|
+
"claimHandler": swapData.claimHandler,
|
|
110
|
+
"claimData": "0x"+swapData.getClaimHash(),
|
|
111
|
+
"refundHandler": swapData.refundHandler,
|
|
112
|
+
"refundData": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
|
|
113
|
+
"securityDeposit": swapData.securityDeposit,
|
|
114
|
+
"claimerBounty": swapData.claimerBounty,
|
|
115
|
+
"depositToken": swapData.depositToken,
|
|
116
|
+
"claimActionHash": ZeroHash,
|
|
117
|
+
"deadline": authExpiry,
|
|
118
|
+
"extraDataHash": keccak256("0x"+(swapData.extraData ?? ""))
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
prefix: this.getAuthPrefix(swapData),
|
|
123
|
+
timeout: authExpiry.toString(10),
|
|
124
|
+
signature
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Checks whether the provided signature data is valid, using preFetchedData if provided and still valid
|
|
130
|
+
*
|
|
131
|
+
* @param sender
|
|
132
|
+
* @param swapData
|
|
133
|
+
* @param timeout
|
|
134
|
+
* @param prefix
|
|
135
|
+
* @param signature
|
|
136
|
+
* @param preFetchData
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
public async isSignatureValid(
|
|
140
|
+
sender: string,
|
|
141
|
+
swapData: EVMSwapData,
|
|
142
|
+
timeout: string,
|
|
143
|
+
prefix: string,
|
|
144
|
+
signature: string,
|
|
145
|
+
preFetchData?: EVMPreFetchVerification
|
|
146
|
+
): Promise<null> {
|
|
147
|
+
if(!swapData.isOfferer(sender) && !swapData.isClaimer(sender))
|
|
148
|
+
throw new SignatureVerificationError("TX sender not offerer nor claimer");
|
|
149
|
+
|
|
150
|
+
const signer = swapData.isOfferer(sender) ? swapData.claimer : swapData.offerer;
|
|
151
|
+
|
|
152
|
+
if(await this.contract.isExpired(sender, swapData)) {
|
|
153
|
+
throw new SignatureVerificationError("Swap will expire too soon!");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if(prefix!==this.getAuthPrefix(swapData)) throw new SignatureVerificationError("Invalid prefix");
|
|
157
|
+
|
|
158
|
+
const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
159
|
+
const timeoutBN = BigInt(timeout);
|
|
160
|
+
const isExpired = (timeoutBN - currentTimestamp) < BigInt(this.contract.authGracePeriod);
|
|
161
|
+
if (isExpired) throw new SignatureVerificationError("Authorization expired!");
|
|
162
|
+
if(await this.isSignatureExpired(timeout, preFetchData)) throw new SignatureVerificationError("Authorization expired!");
|
|
163
|
+
|
|
164
|
+
const valid = await this.root.Signatures.isValidSignature(this.contract.contractAddress, signature, signer, Initialize, "Initialize", {
|
|
165
|
+
"swapHash": "0x"+swapData.getEscrowHash(),
|
|
166
|
+
"offerer": swapData.offerer,
|
|
167
|
+
"claimer": swapData.claimer,
|
|
168
|
+
"amount": swapData.amount,
|
|
169
|
+
"token": swapData.token,
|
|
170
|
+
"payIn": swapData.isPayIn(),
|
|
171
|
+
"payOut": swapData.isPayOut(),
|
|
172
|
+
"trackingReputation": swapData.reputation,
|
|
173
|
+
"claimHandler": swapData.claimHandler,
|
|
174
|
+
"claimData": "0x"+swapData.getClaimHash(),
|
|
175
|
+
"refundHandler": swapData.refundHandler,
|
|
176
|
+
"refundData": swapData.refundData.startsWith("0x") ? swapData.refundData : "0x"+swapData.refundData,
|
|
177
|
+
"securityDeposit": swapData.securityDeposit,
|
|
178
|
+
"claimerBounty": swapData.claimerBounty,
|
|
179
|
+
"depositToken": swapData.depositToken,
|
|
180
|
+
"claimActionHash": ZeroHash,
|
|
181
|
+
"deadline": timeoutBN,
|
|
182
|
+
"extraDataHash": keccak256("0x"+(swapData.extraData ?? ""))
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if(!valid) throw new SignatureVerificationError("Invalid signature!");
|
|
186
|
+
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Gets expiry of the provided signature data, this is a minimum of slot expiry & swap signature expiry
|
|
192
|
+
*
|
|
193
|
+
* @param timeout
|
|
194
|
+
* @public
|
|
195
|
+
*/
|
|
196
|
+
public async getSignatureExpiry(
|
|
197
|
+
timeout: string
|
|
198
|
+
): Promise<number> {
|
|
199
|
+
const now = Date.now();
|
|
200
|
+
const timeoutExpiryTime = (parseInt(timeout)-this.contract.authGracePeriod)*1000;
|
|
201
|
+
|
|
202
|
+
if(timeoutExpiryTime<now) return 0;
|
|
203
|
+
|
|
204
|
+
return timeoutExpiryTime;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Checks whether signature is expired for good, compares the timestamp to the current "pending" block timestamp
|
|
209
|
+
*
|
|
210
|
+
* @param timeout
|
|
211
|
+
* @param preFetchData
|
|
212
|
+
* @public
|
|
213
|
+
*/
|
|
214
|
+
public async isSignatureExpired(
|
|
215
|
+
timeout: string,
|
|
216
|
+
preFetchData?: EVMPreFetchVerification
|
|
217
|
+
): Promise<boolean> {
|
|
218
|
+
if(preFetchData==null || preFetchData.safeBlockTime==null) {
|
|
219
|
+
preFetchData = await this.preFetchForInitSignatureVerification();
|
|
220
|
+
}
|
|
221
|
+
return preFetchData.safeBlockTime > parseInt(timeout);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Creates init transaction with a valid signature from an LP
|
|
226
|
+
*
|
|
227
|
+
* @param sender
|
|
228
|
+
* @param swapData swap to initialize
|
|
229
|
+
* @param timeout init signature timeout
|
|
230
|
+
* @param prefix init signature prefix
|
|
231
|
+
* @param signature init signature
|
|
232
|
+
* @param skipChecks whether to skip signature validity checks
|
|
233
|
+
* @param feeRate fee rate to use for the transaction
|
|
234
|
+
*/
|
|
235
|
+
public async txsInit(
|
|
236
|
+
sender: string,
|
|
237
|
+
swapData: EVMSwapData,
|
|
238
|
+
timeout: string,
|
|
239
|
+
prefix: string,
|
|
240
|
+
signature: string,
|
|
241
|
+
skipChecks?: boolean,
|
|
242
|
+
feeRate?: string
|
|
243
|
+
): Promise<EVMTx[]> {
|
|
244
|
+
if(
|
|
245
|
+
swapData.isClaimer(sender) && swapData.isPayIn() &&
|
|
246
|
+
swapData.isToken(this.root.getNativeCurrencyAddress())
|
|
247
|
+
) throw new Error("Cannot initialize as claimer for payIn=true and native currency!");
|
|
248
|
+
|
|
249
|
+
if(!skipChecks) {
|
|
250
|
+
const [_, payStatus] = await Promise.all([
|
|
251
|
+
swapData.isOfferer(sender) && !swapData.reputation ? Promise.resolve() : tryWithRetries(
|
|
252
|
+
() => this.isSignatureValid(sender, swapData, timeout, prefix, signature),
|
|
253
|
+
this.retryPolicy, (e) => e instanceof SignatureVerificationError
|
|
254
|
+
),
|
|
255
|
+
tryWithRetries(() => this.contract.getCommitStatus(sender, swapData), this.retryPolicy)
|
|
256
|
+
]);
|
|
257
|
+
if(payStatus.type!==SwapCommitStateType.NOT_COMMITED) throw new SwapDataVerificationError("Invoice already being paid for or paid");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
feeRate ??= await this.root.Fees.getFeeRate();
|
|
261
|
+
|
|
262
|
+
const txs: EVMTx[] = [];
|
|
263
|
+
const requiredApprovals: {[address: string]: bigint} = {};
|
|
264
|
+
if(swapData.isPayIn() && swapData.isOfferer(sender)) {
|
|
265
|
+
if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
|
|
266
|
+
requiredApprovals[swapData.token.toLowerCase()] = swapData.amount;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if(swapData.getTotalDeposit() !== 0n) {
|
|
270
|
+
if(!swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
|
|
271
|
+
requiredApprovals[swapData.depositToken.toLowerCase()] ??= 0n;
|
|
272
|
+
requiredApprovals[swapData.depositToken.toLowerCase()] += swapData.getTotalDeposit();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const requiredApprovalTxns = await Promise.all(
|
|
277
|
+
Object.keys(requiredApprovals).map(token => this.root.Tokens.checkAndGetApproveTx(sender, token, requiredApprovals[token], this.contract.contractAddress, feeRate))
|
|
278
|
+
);
|
|
279
|
+
requiredApprovalTxns.forEach(tx => tx!=null && txs.push(tx));
|
|
280
|
+
|
|
281
|
+
txs.push(await this.Init(sender, swapData, BigInt(timeout), signature ?? "0x", feeRate));
|
|
282
|
+
|
|
283
|
+
this.logger.debug("txsInitPayIn(): create swap init TX, swap: "+swapData.getClaimHash()+
|
|
284
|
+
" feerate: "+feeRate);
|
|
285
|
+
|
|
286
|
+
return txs;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private getInitGas(swapData: EVMSwapData): number {
|
|
290
|
+
let totalGas = EVMSwapInit.GasCosts.BASE;
|
|
291
|
+
if(swapData.isPayIn()) {
|
|
292
|
+
if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
|
|
293
|
+
totalGas += EVMSwapInit.GasCosts.ERC20_TRANSFER;
|
|
294
|
+
}
|
|
295
|
+
} else {
|
|
296
|
+
totalGas += EVMSwapInit.GasCosts.LP_VAULT_TRANSFER;
|
|
297
|
+
}
|
|
298
|
+
if(swapData.getTotalDeposit() > 0) {
|
|
299
|
+
if(!swapData.isPayIn() || !swapData.isDepositToken(swapData.token)) {
|
|
300
|
+
if(!swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
|
|
301
|
+
totalGas += EVMSwapInit.GasCosts.ERC20_TRANSFER;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return totalGas;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get the estimated fee of the init transaction
|
|
310
|
+
*/
|
|
311
|
+
async getInitFee(swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
|
|
312
|
+
feeRate ??= await this.root.Fees.getFeeRate();
|
|
313
|
+
let totalFee = EVMFees.getGasFee(this.getInitGas(swapData), feeRate);
|
|
314
|
+
if(swapData.isPayIn()) {
|
|
315
|
+
if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
|
|
316
|
+
totalFee += await this.root.Tokens.getApproveFee(feeRate);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if(swapData.getTotalDeposit() > 0) {
|
|
320
|
+
if(!swapData.isPayIn() || !swapData.isDepositToken(swapData.token)) {
|
|
321
|
+
if(!swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
|
|
322
|
+
totalFee += await this.root.Tokens.getApproveFee(feeRate);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return totalFee;
|
|
328
|
+
}
|
|
326
329
|
}
|