Skip to content

Commit c990e92

Browse files
authored
Merge pull request #713 from Adamant-im/trello.com/c/gOHDDVHJ
[trello.com/c/gOHDDVHJ] Updating Gas algorithm to be more atomic and readable
2 parents ab1df38 + 911076d commit c990e92

File tree

6 files changed

+176
-106
lines changed

6 files changed

+176
-106
lines changed

Adamant.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@
276276
851FF2762D7B3E6B00276625 /* ChatViewController+NavigationControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851FF2752D7B3E5B00276625 /* ChatViewController+NavigationControllerDelegate.swift */; };
277277
85930FFC2D8EF68300AC9D65 /* UserDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85930FFB2D8EF65800AC9D65 /* UserDefaultsManager.swift */; };
278278
85ACCA662D68DC57005658CE /* ChatMessagesSortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85ACCA652D68DC52005658CE /* ChatMessagesSortDescriptor.swift */; };
279+
85956E3A2D7096F5000453E7 /* ERC20ApiWalletService+GasAlgorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85956E392D7096E4000453E7 /* ERC20ApiWalletService+GasAlgorithm.swift */; };
280+
854B2F2C2D71DFCD00A0583E /* ERC20GasAlgorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 854B2F2B2D71DFA700A0583E /* ERC20GasAlgorithm.swift */; };
279281
85B405022D3012D5000AB744 /* AccountViewController+Form.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B405012D3012C7000AB744 /* AccountViewController+Form.swift */; };
280282
85DC0EA82D96C44A00B9CA2C /* TokensAndCoinsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DC0EA72D96C43A00B9CA2C /* TokensAndCoinsViewController.swift */; };
281283
85DC0EAB2D96ECF000B9CA2C /* CoinInfoDTOViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DC0EAA2D96ECF000B9CA2C /* CoinInfoDTOViewController.swift */; };
@@ -1015,6 +1017,8 @@
10151017
851FF2752D7B3E5B00276625 /* ChatViewController+NavigationControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChatViewController+NavigationControllerDelegate.swift"; sourceTree = "<group>"; };
10161018
85930FFB2D8EF65800AC9D65 /* UserDefaultsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsManager.swift; sourceTree = "<group>"; };
10171019
85ACCA652D68DC52005658CE /* ChatMessagesSortDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMessagesSortDescriptor.swift; sourceTree = "<group>"; };
1020+
85956E392D7096E4000453E7 /* ERC20ApiWalletService+GasAlgorithm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ERC20ApiWalletService+GasAlgorithm.swift"; sourceTree = "<group>"; };
1021+
854B2F2B2D71DFA700A0583E /* ERC20GasAlgorithm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ERC20GasAlgorithm.swift; sourceTree = "<group>"; };
10181022
85B405012D3012C7000AB744 /* AccountViewController+Form.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountViewController+Form.swift"; sourceTree = "<group>"; };
10191023
85DC0EA72D96C43A00B9CA2C /* TokensAndCoinsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokensAndCoinsViewController.swift; sourceTree = "<group>"; };
10201024
85DC0EAA2D96ECF000B9CA2C /* CoinInfoDTOViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoinInfoDTOViewController.swift; sourceTree = "<group>"; };
@@ -1859,6 +1863,7 @@
18591863
6449BA5D235CA0930033B936 /* ERC20 */ = {
18601864
isa = PBXGroup;
18611865
children = (
1866+
854B2F2B2D71DFA700A0583E /* ERC20GasAlgorithm.swift */,
18621867
AAC6415A2D44FAFB00619DFE /* ERC20ApiServiceProtocol.swift */,
18631868
6449BA66235CA0930033B936 /* ERC20WalletFactory.swift */,
18641869
6449BA60235CA0930033B936 /* ERC20Wallet.swift */,
@@ -3913,6 +3918,7 @@
39133918
48DA2FD62D4A58D8008F9FC1 /* WalletCollectionViewCell+Model.swift in Sources */,
39143919
3A7BD00E2AA9BCE80045AAB0 /* VibroService.swift in Sources */,
39153920
3AF9DF0D2C049161009A43A8 /* CircularProgressView.swift in Sources */,
3921+
854B2F2C2D71DFCD00A0583E /* ERC20GasAlgorithm.swift in Sources */,
39163922
9306E0932CF8C50E00A99BA4 /* PKGeneratorView.swift in Sources */,
39173923
9306E0942CF8C50E00A99BA4 /* PKGeneratorFactory.swift in Sources */,
39183924
9306E0952CF8C50E00A99BA4 /* PKGeneratorViewModel.swift in Sources */,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// ERC20GasAlgorithm.swift
3+
// Adamant
4+
//
5+
// Created by Sergei Veretennikov on 28.02.2025.
6+
// Copyright © 2025 Adamant. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import BigInt
11+
12+
protocol ERC20GasAlgorithmComputable {
13+
var reliabilityGasPricePercent: BigUInt { get }
14+
var reliabilityGasLimitPercent: BigUInt { get }
15+
var increasedGasPricePercent: Decimal { get }
16+
}
17+
18+
extension ERC20GasAlgorithmComputable {
19+
func updateGasAndFee(
20+
gasPrice: BigUInt,
21+
gasLimit: BigUInt,
22+
gasPriceCoeficient: Decimal,
23+
completion: @escaping (_ gasPrice: BigUInt, _ gasLimit: BigUInt, _ newFee: Decimal) -> Void
24+
) {
25+
let reliabilityGasPricePercent = gasPrice / reliabilityGasPricePercent
26+
let reliabilityGasLimitPercent = gasLimit / reliabilityGasLimitPercent
27+
28+
let reliableGasPrice = reliabilityGasPricePercent + gasPrice
29+
let reliableGasLimit = reliabilityGasLimitPercent + gasLimit
30+
31+
let finalGasPrice = BigUInt(reliableGasPrice.asDouble() * gasPriceCoeficient.doubleValue)
32+
let newFee = (finalGasPrice * reliableGasLimit).asDecimal(exponent: EthWalletService.currencyExponent)
33+
34+
completion(
35+
finalGasPrice,
36+
reliableGasLimit,
37+
newFee
38+
)
39+
}
40+
}

Adamant/Modules/Wallets/ERC20/ERC20WalletService.swift

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,63 +16,63 @@ import Alamofire
1616
import Combine
1717
import CommonKit
1818

19-
final class ERC20WalletService: WalletCoreProtocol, @unchecked Sendable {
19+
final class ERC20WalletService: WalletCoreProtocol, ERC20GasAlgorithmComputable, @unchecked Sendable {
2020
// MARK: - Constants
2121
let addressRegex = try! NSRegularExpression(pattern: "^0x[a-fA-F0-9]{40}$")
2222

2323
var minBalance: Decimal = 0
2424
var minAmount: Decimal = 0
2525

2626
var tokenSymbol: String {
27-
return token.symbol
27+
token.symbol
2828
}
2929

3030
var tokenName: String {
31-
return token.name
31+
token.name
3232
}
3333

3434
var tokenLogo: UIImage {
35-
return token.logo
35+
token.logo
3636
}
3737

3838
static var tokenNetworkSymbol: String {
39-
return "ERC20"
39+
"ERC20"
4040
}
4141

4242
var consistencyMaxTime: Double {
43-
return 1200
43+
1200
4444
}
4545

4646
var tokenContract: String {
47-
return token.contractAddress
47+
token.contractAddress
4848
}
4949

5050
var tokenUniqueID: String {
5151
Self.tokenNetworkSymbol + tokenSymbol + tokenContract
5252
}
5353

5454
var defaultVisibility: Bool {
55-
return token.defaultVisibility
55+
token.defaultVisibility
5656
}
5757

5858
var defaultOrdinalLevel: Int? {
59-
return token.defaultOrdinalLevel
59+
token.defaultOrdinalLevel
6060
}
6161

6262
var richMessageType: String {
63-
return Self.richMessageType
63+
Self.richMessageType
6464
}
6565

6666
var qqPrefix: String {
67-
return EthWalletService.qqPrefix
67+
EthWalletService.qqPrefix
6868
}
6969

7070
var isSupportIncreaseFee: Bool {
71-
return true
71+
true
7272
}
7373

7474
var isIncreaseFeeEnabled: Bool {
75-
return increaseFeeService.isIncreaseFeeEnabled(for: tokenUniqueID)
75+
increaseFeeService.isIncreaseFeeEnabled(for: tokenUniqueID)
7676
}
7777

7878
var nodeGroups: [NodeGroup] {
@@ -95,7 +95,19 @@ final class ERC20WalletService: WalletCoreProtocol, @unchecked Sendable {
9595
private(set) var isWarningGasPrice = false
9696

9797
var isTransactionFeeValid: Bool {
98-
return ethWallet?.balance ?? 0 > transactionFee
98+
ethWallet?.balance ?? 0 > transactionFee
99+
}
100+
101+
var reliabilityGasPricePercent: BigUInt {
102+
BigUInt(token.reliabilityGasPricePercent)
103+
}
104+
105+
var reliabilityGasLimitPercent: BigUInt {
106+
BigUInt(token.reliabilityGasLimitPercent)
107+
}
108+
109+
var increasedGasPricePercent: Decimal {
110+
token.increasedGasPricePercent
99111
}
100112

101113
static let transferGas: Decimal = 21000
@@ -283,42 +295,41 @@ final class ERC20WalletService: WalletCoreProtocol, @unchecked Sendable {
283295
}
284296

285297
func calculateFee(for address: EthereumAddress? = nil) async {
286-
let priceRaw = try? await getGasPrices()
287-
let gasLimitRaw = try? await getGasLimit(to: address)
288-
289-
var price = priceRaw ?? BigUInt(token.defaultGasPriceGwei).toWei()
290-
var gasLimit = gasLimitRaw ?? BigUInt(token.defaultGasLimit)
291-
292-
let pricePercent = price * BigUInt(token.reliabilityGasPricePercent) / 100
293-
let gasLimitPercent = gasLimit * BigUInt(token.reliabilityGasLimitPercent) / 100
294-
295-
price = priceRaw == nil
296-
? price
297-
: price + pricePercent
298-
299-
gasLimit = gasLimitRaw == nil
300-
? gasLimit
301-
: gasLimit + gasLimitPercent
298+
// Setting initial
299+
async let pricePriceAsync = getGasPrices()
300+
async let gasLimitAsync = getGasLimit(to: address)
301+
var gasPriceCoeficient: Decimal = 1
302+
if isIncreaseFeeEnabled {
303+
gasPriceCoeficient += token.increasedGasPricePercent / 100
304+
}
302305

303-
var newFee = (price * gasLimit).asDecimal(exponent: EthWalletService.currencyExponent)
306+
let gasPrice, gasLimit: BigUInt
304307

305-
newFee = isIncreaseFeeEnabled
306-
? newFee * defaultIncreaseFee
307-
: newFee
308-
309-
guard transactionFee != newFee else { return }
310-
311-
transactionFee = newFee
312-
let incGasPrice = UInt64(price.asDouble() * defaultIncreaseFee.doubleValue)
313-
314-
gasPrice = isIncreaseFeeEnabled
315-
? BigUInt(integerLiteral: incGasPrice)
316-
: price
317-
318-
isWarningGasPrice = gasPrice >= BigUInt(token.warningGasPriceGwei).toWei()
319-
self.gasLimit = gasLimit
308+
// Getting gas data
309+
do {
310+
let (gasPriceFromChain, gasLimitFromChain) = try await (pricePriceAsync, gasLimitAsync)
311+
try Task.checkCancellation()
312+
gasPrice = gasPriceFromChain
313+
gasLimit = gasLimitFromChain
314+
} catch {
315+
gasPrice = BigUInt(token.defaultGasPriceGwei).toWei()
316+
gasLimit = BigUInt(token.defaultGasLimit)
317+
}
320318

321-
NotificationCenter.default.post(name: transactionFeeUpdated, object: self, userInfo: nil)
319+
// Updating localy
320+
updateGasAndFee(
321+
gasPrice: gasPrice,
322+
gasLimit: gasLimit,
323+
gasPriceCoeficient: gasPriceCoeficient
324+
) { [weak self] gasPrice, gasLimit, newFee in
325+
guard let self else { return }
326+
self.gasPrice = gasPrice
327+
self.gasLimit = gasLimit
328+
guard transactionFee != newFee else { return }
329+
transactionFee = newFee
330+
isWarningGasPrice = gasPrice >= BigUInt(token.warningGasPriceGwei).toWei()
331+
NotificationCenter.default.post(name: transactionFeeUpdated, object: self, userInfo: nil)
332+
}
322333
}
323334

324335
func validate(address: String) -> AddressValidationResult {

0 commit comments

Comments
 (0)