Skip to content

Commit

Permalink
[IOS-138] Replace get expected rate with Kyber node call (KYRDTeam#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrQKyber authored Sep 17, 2020
1 parent 5662e23 commit 00cea02
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 27 deletions.
2 changes: 1 addition & 1 deletion KyberNetwork/EtherClient/EtherServiceRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct EtherServiceKyberRequest<Batch: JSONRPCKit.Batch>: APIKit.Request {

var baseURL: URL {
// Change to KyberNetwork endpoint
if let customRPC = KNEnvironment.default.customRPC, let path = URL(string: customRPC.endpointKyber + KNEnvironment.default.nodeEndpoint) {
if let path = URL(string: KNEnvironment.default.kyberEndpointURL + KNEnvironment.default.nodeEndpoint) {
return path
}
let config = Config()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,11 @@ enum KNEnvironment: Int {
default: return KNSecret.devApiURL
}
}

var kyberEndpointURL: String {
switch KNEnvironment.default {
case .mainnetTest, .production, .staging: return KNSecret.mainnetKyberNodeURL
default: return KNSecret.ropstenKyberNodeURL
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,13 @@ class KNExternalProvider {
}

// MARK: Rate
func getExpectedRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", completion: @escaping (Result<(BigInt, BigInt), AnyError>) -> Void) {
func getExpectedRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", withKyber: Bool = false, completion: @escaping (Result<(BigInt, BigInt), AnyError>) -> Void) {
KNGeneralProvider.shared.getExpectedRate(
from: from,
to: to,
amount: amount,
hint: hint,
withKyber: withKyber,
completion: completion
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class KNGeneralProvider {
}()

lazy var web3SwiftKyber: Web3Swift = {
if let customRPC = KNEnvironment.default.customRPC, let path = URL(string: customRPC.endpointKyber + KNEnvironment.default.nodeEndpoint) {
if let path = URL(string: KNEnvironment.default.kyberEndpointURL + KNEnvironment.default.nodeEndpoint) {
return Web3Swift(url: path)
} else {
return Web3Swift()
Expand Down Expand Up @@ -186,24 +186,41 @@ class KNGeneralProvider {
}
}

func getExpectedRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", completion: @escaping (Result<(BigInt, BigInt), AnyError>) -> Void) {
func getExpectedRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", withKyber: Bool = false, completion: @escaping (Result<(BigInt, BigInt), AnyError>) -> Void) {
let source: Address = Address(string: from.contract)!
let dest: Address = Address(string: to.contract)!
self.getExpectedRateEncodeData(source: source, dest: dest, amount: amount, hint: hint) { [weak self] dataResult in
guard let `self` = self else { return }
switch dataResult {
case .success(let data):
let callRequest = CallRequest(to: self.networkAddress.description, data: data)
let getRateRequest = EtherServiceAlchemyRequest(batch: BatchFactory().create(callRequest))
DispatchQueue.global().async {
Session.send(getRateRequest) { [weak self] getRateResult in
guard let `self` = self else { return }
DispatchQueue.main.async {
switch getRateResult {
case .success(let rateData):
self.getExpectedRateDecodeData(rateData: rateData, completion: completion)
case .failure(let error):
completion(.failure(AnyError(error)))
if withKyber {
let getRateRequest = EtherServiceKyberRequest(batch: BatchFactory().create(callRequest))
DispatchQueue.global().async {
Session.send(getRateRequest) { [weak self] getRateResult in
guard let `self` = self else { return }
DispatchQueue.main.async {
switch getRateResult {
case .success(let rateData):
self.getExpectedRateDecodeData(rateData: rateData, completion: completion)
case .failure(let error):
completion(.failure(AnyError(error)))
}
}
}
}
} else {
let getRateRequest = EtherServiceAlchemyRequest(batch: BatchFactory().create(callRequest))
DispatchQueue.global().async {
Session.send(getRateRequest) { [weak self] getRateResult in
guard let `self` = self else { return }
DispatchQueue.main.async {
switch getRateResult {
case .success(let rateData):
self.getExpectedRateDecodeData(rateData: rateData, completion: completion)
case .failure(let error):
completion(.failure(AnyError(error)))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Moya

enum KSwapViewEvent {
case searchToken(from: TokenObject, to: TokenObject, isSource: Bool)
case estimateRate(from: TokenObject, to: TokenObject, amount: BigInt, showError: Bool)
case estimateRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String, showError: Bool)
case estimateComparedRate(from: TokenObject, to: TokenObject, hint: String) // compare to show warning
case estimateGas(from: TokenObject, to: TokenObject, amount: BigInt, gasPrice: BigInt, hint: String)
case setGasPrice(gasPrice: BigInt, gasLimit: BigInt)
Expand Down Expand Up @@ -157,12 +157,13 @@ class KSwapViewController: KNBaseViewController {
self.estRateTimer?.invalidate()
self.updateEstimatedRate(showError: true, showLoading: true)
self.updateReferencePrice()
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFrom)
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFromStringParameter)
self.estRateTimer = Timer.scheduledTimer(
withTimeInterval: KNLoadingInterval.seconds30,
repeats: true,
block: { [weak self] _ in
self?.updateEstimatedRate()
guard let `self` = self else { return }
self.updateEstimatedRate()
}
)

Expand All @@ -173,7 +174,9 @@ class KSwapViewController: KNBaseViewController {
withTimeInterval: KNLoadingInterval.seconds60,
repeats: true,
block: { [weak self] _ in
self?.updateEstimatedGasLimit()
guard let `self` = self else { return }
self.updateEstimatedGasLimit()
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFromStringParameter)
}
)

Expand Down Expand Up @@ -571,6 +574,7 @@ class KSwapViewController: KNBaseViewController {
from: self.viewModel.from,
to: self.viewModel.to,
amount: self.viewModel.amountToEstimate,
hint: self.viewModel.getHint(from: self.viewModel.from.address, to: self.viewModel.to.address),
showError: showError
)
self.delegate?.kSwapViewController(self, run: event)
Expand Down Expand Up @@ -742,7 +746,7 @@ class KSwapViewController: KNBaseViewController {
guard self.isViewSetup else {
return
}
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFrom)
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFromStringParameter)
}

func update(notificationsCount: Int) {
Expand Down Expand Up @@ -1077,7 +1081,7 @@ extension KSwapViewController {
self.updateRateDestAmountDidChangeIfNeeded(prevDest: BigInt(0), isForceLoad: true)
}
self.updateEstimatedGasLimit()
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFrom)
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFromStringParameter)
self.advancedSettingsView.updateIsUsingReverseRoutingStatus(value: true)
self.viewModel.isUsingReverseRouting = true
self.view.layoutIfNeeded()
Expand Down Expand Up @@ -1231,6 +1235,7 @@ extension KSwapViewController: UITextFieldDelegate {
if self.viewModel.isFocusingFromAmount {
self.fromAmountTextField.textColor = self.viewModel.amountTextFieldColor
self.toAmountTextField.textColor = UIColor.Kyber.mirage
self.updateSwapHint(from: self.viewModel.from, to: self.viewModel.to, amount: self.viewModel.amountFromStringParameter)
} else {
self.toAmountTextField.textColor = self.viewModel.amountTextFieldColor
self.fromAmountTextField.textColor = UIColor.Kyber.mirage
Expand Down Expand Up @@ -1363,6 +1368,7 @@ extension KSwapViewController: KAdvancedSettingsViewDelegate {
case .changeIsUsingReverseRouting(let value):
self.viewModel.isUsingReverseRouting = value
self.updateEstimatedGasLimit()
self.updateEstimatedRate(showError: true)
case .reverseRoutingHelpPress:
self.showBottomBannerView(
message: "Reduce.gas.costs.by.routing.your.trade.to.predefined.reserves".toBeLocalised(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,15 @@ class KSwapViewModel {
return ethBal >= fee
}

var amountFromStringParameter: String {
var param = self.amountFrom.removeGroupSeparator()
let decimals: Character = EtherNumberFormatter.short.decimalSeparator.first!
if String(decimals) != "." {
param = param.replacingOccurrences(of: String(decimals), with: ".")
}
return param
}

// MARK: Update data
func updateWallet(_ wallet: Wallet) {
self.wallet = wallet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,8 @@ extension KNExchangeTokenCoordinator: KSwapViewControllerDelegate {
switch event {
case .searchToken(let from, let to, let isSource):
self.openSearchToken(from: from, to: to, isSource: isSource)
case .estimateRate(let from, let to, let amount, let showError):
self.updateExpectedRateFromAPIIfNeeded(from: from, to: to, amount: amount, showError: showError)
case .estimateRate(let from, let to, let amount, let hint, let showError):
self.updateExpectedRateWithKyberIfNeeded(from: from, to: to, amount: amount, hint: hint, showError: showError)
case .estimateComparedRate(let from, let to, let hint):
self.updateComparedEstimateRate(from: from, to: to, hint: hint)
case .estimateGas(let from, let to, let amount, let gasPrice, let hint):
Expand Down Expand Up @@ -677,8 +677,8 @@ extension KNExchangeTokenCoordinator: KSwapViewControllerDelegate {
}

// Call contract to get estimate rate with src, dest, srcAmount
fileprivate func updateEstimatedRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", showError: Bool, completion: ((Error?) -> Void)? = nil) {
self.getExpectedExchangeRate(from: from, to: to, amount: amount, hint: hint) { [weak self] result in
fileprivate func updateEstimatedRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", showError: Bool, withKyber: Bool = false, completion: ((Error?) -> Void)? = nil) {
self.getExpectedExchangeRate(from: from, to: to, amount: amount, hint: hint, withKyber: withKyber) { [weak self] result in
guard let `self` = self else { return }
switch result {
case .success(let data):
Expand All @@ -691,7 +691,7 @@ extension KNExchangeTokenCoordinator: KSwapViewControllerDelegate {
)
completion?(nil)
case .failure(let error):
if showError {
if showError && !withKyber {
if case let err as APIKit.SessionTaskError = error.error, case .connectionError = err {
self.navigationController.showErrorTopBannerMessage(
with: NSLocalizedString("error", value: "Error", comment: ""),
Expand All @@ -713,12 +713,15 @@ extension KNExchangeTokenCoordinator: KSwapViewControllerDelegate {
slippageRate: BigInt(0)
)
}
if withKyber {
self.updateExpectedRateFromAPIIfNeeded(from: from, to: to, amount: amount, showError: showError)
}
completion?(error)
}
}
}

fileprivate func getExpectedExchangeRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", completion: ((Result<(BigInt, BigInt), AnyError>) -> Void)? = nil) {
fileprivate func getExpectedExchangeRate(from: TokenObject, to: TokenObject, amount: BigInt, hint: String = "", withKyber: Bool = false, completion: ((Result<(BigInt, BigInt), AnyError>) -> Void)? = nil) {
if from == to {
let rate = BigInt(10).power(from.decimals)
let slippageRate = rate * BigInt(97) / BigInt(100)
Expand All @@ -729,7 +732,8 @@ extension KNExchangeTokenCoordinator: KSwapViewControllerDelegate {
from: from,
to: to,
amount: amount,
hint: hint
hint: hint,
withKyber: withKyber
) { (result) in
var estRate: BigInt = BigInt(0)
var slippageRate: BigInt = BigInt(0)
Expand All @@ -746,6 +750,16 @@ extension KNExchangeTokenCoordinator: KSwapViewControllerDelegate {
}
}

func updateExpectedRateWithKyberIfNeeded(from: TokenObject, to: TokenObject, amount: BigInt, hint: String, showError: Bool) {
if hint.isEmpty || hint == "0x" {
self.updateExpectedRateFromAPIIfNeeded(from: from, to: to, amount: amount, showError: showError)
} else {
DispatchQueue.main.async {
self.updateEstimatedRate(from: from, to: to, amount: amount, hint: hint, showError: showError, withKyber: true)
}
}
}

func updateExpectedRateFromAPIIfNeeded(from: TokenObject, to: TokenObject, amount: BigInt, showError: Bool) {
let src = from.contract.lowercased()
let dest = to.contract.lowercased()
Expand Down

0 comments on commit 00cea02

Please sign in to comment.