Skip to content

Commit

Permalink
IOS-7720 Mantle token (Express): error when get fee for permission (#815
Browse files Browse the repository at this point in the history
)
  • Loading branch information
amuraveinik authored Aug 26, 2024
1 parent b81a6ce commit 7e265cd
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 27 deletions.
4 changes: 4 additions & 0 deletions BlockchainSdk.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@
DA82433F27A2B07800CFC2C0 /* PolkadotNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA82433E27A2B07800CFC2C0 /* PolkadotNetwork.swift */; };
DA82434127A2B0AD00CFC2C0 /* PolkadotTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA82434027A2B0AD00CFC2C0 /* PolkadotTarget.swift */; };
DA82434327A2B0C100CFC2C0 /* PolkadotResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA82434227A2B0C100CFC2C0 /* PolkadotResponse.swift */; };
DA95AE092C7CB1DE0055740F /* MantleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA95AE082C7CB1DE0055740F /* MantleUtils.swift */; };
DA9EA73F29EE958500CAE6F2 /* CosmosTransactionParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA73E29EE958500CAE6F2 /* CosmosTransactionParams.swift */; };
DA9F76E927EC8AEB00F0665C /* TronAddressService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9F76E827EC8AEB00F0665C /* TronAddressService.swift */; };
DA9F76EC27EC9A2900F0665C /* TronWalletManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9F76EB27EC9A2900F0665C /* TronWalletManager.swift */; };
Expand Down Expand Up @@ -1461,6 +1462,7 @@
DA82433E27A2B07800CFC2C0 /* PolkadotNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolkadotNetwork.swift; sourceTree = "<group>"; };
DA82434027A2B0AD00CFC2C0 /* PolkadotTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolkadotTarget.swift; sourceTree = "<group>"; };
DA82434227A2B0C100CFC2C0 /* PolkadotResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolkadotResponse.swift; sourceTree = "<group>"; };
DA95AE082C7CB1DE0055740F /* MantleUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MantleUtils.swift; sourceTree = "<group>"; };
DA9EA73E29EE958500CAE6F2 /* CosmosTransactionParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CosmosTransactionParams.swift; sourceTree = "<group>"; };
DA9F76E827EC8AEB00F0665C /* TronAddressService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TronAddressService.swift; sourceTree = "<group>"; };
DA9F76EB27EC9A2900F0665C /* TronWalletManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TronWalletManager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3411,6 +3413,7 @@
children = (
DA1BA9A82C454C53006F6839 /* MantleWalletAssembly.swift */,
DA1BA9A62C454AFB006F6839 /* MantleWalletManager.swift */,
DA95AE082C7CB1DE0055740F /* MantleUtils.swift */,
);
path = Mantle;
sourceTree = "<group>";
Expand Down Expand Up @@ -5187,6 +5190,7 @@
B69824812B71A8F800E1333D /* HederaNetworkResult.ExchangeRate.swift in Sources */,
B6D346002AD9450D0009D1B2 /* NEARTransactionBuilder.swift in Sources */,
B00DF9A02BBEACA2004397CB /* QuickNodeAPIResolver.swift in Sources */,
DA95AE092C7CB1DE0055740F /* MantleUtils.swift in Sources */,
EF2D9DCF2BC40E280055C485 /* Result+.swift in Sources */,
EF5F1B9729C9C0500093307B /* Fee.swift in Sources */,
B6A71D982B553E7900039991 /* FeePaidCurrency.swift in Sources */,
Expand Down
22 changes: 22 additions & 0 deletions BlockchainSdk/Blockchains/Mantle/MantleUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// MantleUtils.swift
// BlockchainSdk
//
// Created by Aleksei Muraveinik on 26.08.24.
// Copyright © 2024 Tangem AG. All rights reserved.
//

import BigInt

public enum MantleUtils {
public static let feeGasLimitMultiplier = 1.6
static let signGasLimitMultiplier = 0.7

public static func multiplyGasLimit(_ gasLimit: Int, with multiplier: Double) -> BigUInt {
multiplyGasLimit(BigUInt(gasLimit), with: multiplier)
}

static func multiplyGasLimit(_ gasLimit: BigUInt, with multiplier: Double) -> BigUInt {
BigUInt(ceil(Double(gasLimit) * multiplier))
}
}
70 changes: 43 additions & 27 deletions BlockchainSdk/Blockchains/Mantle/MantleWalletManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,30 @@

import BigInt
import Combine
import Foundation

// This is a workaround for sending a Mantle transaction.
// Unfortunately, Mantle's current implementation does not conform to our existing fee calculation rules.
// https://tangem.slack.com/archives/GMXC6PP71/p1719591856597299?thread_ts=1714215815.690169&cid=GMXC6PP71
final class MantleWalletManager: EthereumWalletManager {
override func getFee(destination: String, value: String?, data: Data?) -> AnyPublisher<[Fee], any Error> {
let blockchain = wallet.blockchain

let adjustedValue = value
.flatMap { value in
EthereumUtils.parseEthereumDecimal(value, decimalsCount: blockchain.decimalCount)
}
.flatMap { parsedValue in
Amount(
with: blockchain,
type: .coin,
value: parsedValue - (1 / blockchain.decimalValue)
)
.encodedForSend
}

return super.getFee(destination: destination, value: adjustedValue, data: data)
.withWeakCaptureOf(self)
.tryMap { walletManager, fees in
try fees.map { fee in
try walletManager.mapMantleFee(fee, gasLimitMultiplier: 1.6)
}
super.getFee(
destination: destination,
value: prepareAdjustedValue(value: value),
data: data
)
.withWeakCaptureOf(self)
.tryMap { walletManager, fees in
try fees.map { fee in
try walletManager.mapMantleFee(fee, gasLimitMultiplier: MantleUtils.feeGasLimitMultiplier)
}
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}

override func sign(_ transaction: Transaction, signer: any TransactionSigner) -> AnyPublisher<String, any Error> {
var transaction = transaction
do {
transaction.fee = try mapMantleFee(transaction.fee, gasLimitMultiplier: 0.7)
transaction.fee = try mapMantleFee(transaction.fee, gasLimitMultiplier: MantleUtils.signGasLimitMultiplier)
} catch {
return Fail(error: error).eraseToAnyPublisher()
}
Expand All @@ -53,7 +41,7 @@ final class MantleWalletManager: EthereumWalletManager {
override func getGasLimit(to: String, from: String, value: String?, data: String?) -> AnyPublisher<BigUInt, any Error> {
super.getGasLimit(to: to, from: from, value: value, data: data)
.map { gasLimit in
BigUInt(ceil(Double(gasLimit) * 1.6))
MantleUtils.multiplyGasLimit(gasLimit, with: MantleUtils.feeGasLimitMultiplier)
}
.eraseToAnyPublisher()
}
Expand All @@ -66,13 +54,13 @@ private extension MantleWalletManager {
let parameters: any EthereumFeeParameters = switch fee.parameters {
case let parameters as EthereumEIP1559FeeParameters:
EthereumEIP1559FeeParameters(
gasLimit: BigUInt(ceil(Double(parameters.gasLimit) * gasLimitMultiplier)),
gasLimit: MantleUtils.multiplyGasLimit(parameters.gasLimit, with: gasLimitMultiplier),
maxFeePerGas: parameters.maxFeePerGas,
priorityFee: parameters.priorityFee
)
case let parameters as EthereumLegacyFeeParameters:
EthereumLegacyFeeParameters(
gasLimit: BigUInt(ceil(Double(parameters.gasLimit) * gasLimitMultiplier)),
gasLimit: MantleUtils.multiplyGasLimit(parameters.gasLimit, with: gasLimitMultiplier),
gasPrice: parameters.gasPrice
)
default:
Expand All @@ -85,4 +73,32 @@ private extension MantleWalletManager {

return Fee(amount, parameters: parameters)
}

func prepareAdjustedValue(value: String?) -> String? {
guard let value, let currentBalance = wallet.amounts[.coin]?.value else {
return nil
}

let parsedValue = EthereumUtils.parseEthereumDecimal(
value,
decimalsCount: wallet.blockchain.decimalCount
)

guard let parsedValue else {
return nil
}

let blockchain = wallet.blockchain
let delta = blockchain.minimumValue

let shouldSubtractPenny = currentBalance.isEqual(to: parsedValue, delta: delta)
let valueToSubtract = shouldSubtractPenny ? delta : 0

return Amount(
with: blockchain,
type: .coin,
value: parsedValue - valueToSubtract
)
.encodedForSend
}
}
4 changes: 4 additions & 0 deletions BlockchainSdk/Common/Blockchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,10 @@ extension Blockchain {
public var decimalValue: Decimal {
return pow(Decimal(10), decimalCount)
}

public var minimumValue: Decimal {
1 / decimalValue
}
}

// MARK: - Card's factory
Expand Down
4 changes: 4 additions & 0 deletions BlockchainSdk/Extensions/Decimal+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ extension Decimal {
var roundedDecimalNumber: NSDecimalNumber {
rounded(roundingMode: .up) as NSDecimalNumber
}

public func isEqual(to value: Decimal, delta: Decimal) -> Bool {
abs(self - value) <= delta
}
}

// MARK: - Point moving
Expand Down

0 comments on commit 7e265cd

Please sign in to comment.