-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathSwapFee.kt
113 lines (96 loc) · 4.5 KB
/
SwapFee.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package org.p2p.wallet.swap.model.orca
import java.math.BigDecimal
import java.math.BigInteger
import kotlinx.parcelize.IgnoredOnParcel
import org.p2p.core.token.Token
import org.p2p.core.utils.Constants.SOL_SYMBOL
import org.p2p.core.utils.SOL_DECIMALS
import org.p2p.core.utils.asApproximateUsd
import org.p2p.core.utils.formatToken
import org.p2p.core.utils.fromLamports
import org.p2p.core.utils.isLessThan
import org.p2p.core.utils.isMoreThan
import org.p2p.core.utils.scaleSix
import org.p2p.core.utils.toUsd
import org.p2p.wallet.feerelayer.model.FeePayerSelectionStrategy
import org.p2p.wallet.send.model.FeePayerState
import org.p2p.wallet.swap.model.FeeRelayerSwapFee
class SwapFee constructor(
private val fee: FeeRelayerSwapFee,
private val feePayerToken: Token.Active,
private val sourceToken: Token.Active,
destination: Token,
private val solToken: Token.Active?
) {
@IgnoredOnParcel
val sourceTokenSymbol: String
get() = sourceToken.tokenSymbol
fun calculateFeePayerState(
strategy: FeePayerSelectionStrategy,
sourceTokenTotal: BigInteger,
inputAmount: BigInteger
): FeePayerState {
val isSourceSol = sourceTokenSymbol == SOL_SYMBOL
val isAllowedToCorrectAmount = strategy == FeePayerSelectionStrategy.CORRECT_AMOUNT
val totalNeeded = fee.feeInPayingToken + inputAmount
val isEnoughSolBalance = solToken?.let { !it.totalInLamports.isLessThan(fee.feeInSol) } ?: false
val shouldTryReduceAmount = isAllowedToCorrectAmount && !isSourceSol && !isEnoughSolBalance
return when {
// if there is not enough SPL token balance to cover amount and fee, then try to reduce input amount
shouldTryReduceAmount && sourceTokenTotal.isLessThan(totalNeeded) -> {
val diff = totalNeeded - sourceTokenTotal
val desiredAmount = if (diff.isLessThan(inputAmount)) inputAmount - diff else null
if (desiredAmount != null) FeePayerState.ReduceInputAmount(desiredAmount) else FeePayerState.SwitchToSol
}
// if there is enough SPL token balance to cover amount and fee
!isSourceSol && sourceTokenTotal.isMoreThan(totalNeeded) ->
FeePayerState.SwitchToSpl(sourceToken)
else ->
FeePayerState.SwitchToSol
}
}
@Deprecated("Old")
fun isEnoughToCoverExpenses(sourceTokenTotal: BigInteger, inputAmount: BigInteger): Boolean =
when {
// if source is SOL, then fee payer is SOL as well
sourceTokenSymbol == SOL_SYMBOL ->
sourceTokenTotal >= inputAmount + fee.feeInSol
// assuming that source token is not SOL
feePayerToken.isSOL ->
sourceTokenTotal >= inputAmount && feePayerTotalLamports > fee.feeInSol
// assuming that source token and fee payer are same
else ->
sourceTokenTotal >= inputAmount + fee.feeInPayingToken
}
val feeAmountInPayingToken: BigDecimal
get() = fee.feeInPayingToken.fromLamports(feePayerToken.decimals).scaleSix()
val feeAmountInSol: BigDecimal
get() = fee.feeInSol.fromLamports(SOL_DECIMALS).scaleSix()
val feePayerSymbol: String = feePayerToken.tokenSymbol
val isFreeTransactionAvailable: Boolean = fee.isFreeTransactionAvailable
val transactionFee: String
get() = "${currentDecimals.formatToken()} ${feePayerToken.tokenSymbol}"
val accountCreationToken: String =
if (destination is Token.Other) destination.tokenSymbol else SOL_SYMBOL
val accountCreationFee: String
get() = "${accountCreationFeeDecimals.formatToken()} ${feePayerToken.tokenSymbol}"
val accountCreationFeeUsd: String? =
accountCreationFeeUsdDecimals?.asApproximateUsd()
private val accountCreationFeeDecimals: BigDecimal
get() {
return if (feePayerToken.isSOL) {
fee.feeInSol.fromLamports(feePayerToken.decimals)
} else {
fee.feeInPayingToken.fromLamports(feePayerToken.decimals)
}
.scaleSix()
}
private val accountCreationFeeUsdDecimals: BigDecimal?
get() = accountCreationFeeDecimals.toUsd(feePayerToken.rate)
private val currentDecimals: BigDecimal =
(if (feePayerToken.isSOL) fee.feeInSol else fee.feeInPayingToken)
.fromLamports(feePayerToken.decimals)
.scaleSix()
private val feePayerTotalLamports: BigInteger
get() = feePayerToken.totalInLamports
}