mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-09 13:56:10 +00:00
feat(@desktop/wallet): Create a new send module to clear out old logic and switch the old one to the new one later, once the old sendModal is not used anymore
fixes #16919
This commit is contained in:
parent
751f27498c
commit
37a06fc3be
@ -70,6 +70,9 @@ method buySellCryptoModuleDidLoad*(self: AccessInterface) {.base.} =
|
|||||||
method sendModuleDidLoad*(self: AccessInterface) {.base.} =
|
method sendModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method newSendModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method overviewModuleDidLoad*(self: AccessInterface) {.base.} =
|
method overviewModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import ./buy_sell_crypto/module as buy_sell_crypto_module
|
|||||||
import ./networks/module as networks_module
|
import ./networks/module as networks_module
|
||||||
import ./overview/module as overview_module
|
import ./overview/module as overview_module
|
||||||
import ./send/module as send_module
|
import ./send/module as send_module
|
||||||
|
import ./send_new/module as new_send_module
|
||||||
|
|
||||||
import ./activity/controller as activityc
|
import ./activity/controller as activityc
|
||||||
|
|
||||||
@ -70,6 +71,8 @@ type
|
|||||||
allCollectiblesModule: all_collectibles_module.AccessInterface
|
allCollectiblesModule: all_collectibles_module.AccessInterface
|
||||||
assetsModule: assets_module.AccessInterface
|
assetsModule: assets_module.AccessInterface
|
||||||
sendModule: send_module.AccessInterface
|
sendModule: send_module.AccessInterface
|
||||||
|
# TODO: replace this with sendModule when old one is removed
|
||||||
|
newSendModule: new_send_module.AccessInterface
|
||||||
savedAddressesModule: saved_addresses_module.AccessInterface
|
savedAddressesModule: saved_addresses_module.AccessInterface
|
||||||
buySellCryptoModule: buy_sell_crypto_module.AccessInterface
|
buySellCryptoModule: buy_sell_crypto_module.AccessInterface
|
||||||
overviewModule: overview_module.AccessInterface
|
overviewModule: overview_module.AccessInterface
|
||||||
@ -141,6 +144,7 @@ proc newModule*(
|
|||||||
currencyService)
|
currencyService)
|
||||||
result.sendModule = send_module.newModule(result, events, walletAccountService, networkService, currencyService,
|
result.sendModule = send_module.newModule(result, events, walletAccountService, networkService, currencyService,
|
||||||
transactionService, keycardService)
|
transactionService, keycardService)
|
||||||
|
result.newSendModule = newSendModule.newModule(result, events, walletAccountService, networkService, transactionService, keycardService)
|
||||||
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
|
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
|
||||||
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, rampService)
|
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, rampService)
|
||||||
result.overviewModule = overview_module.newModule(result, events, walletAccountService, currencyService)
|
result.overviewModule = overview_module.newModule(result, events, walletAccountService, currencyService)
|
||||||
@ -185,6 +189,7 @@ method delete*(self: Module) =
|
|||||||
self.savedAddressesModule.delete
|
self.savedAddressesModule.delete
|
||||||
self.buySellCryptoModule.delete
|
self.buySellCryptoModule.delete
|
||||||
self.sendModule.delete
|
self.sendModule.delete
|
||||||
|
self.newSendModule.delete
|
||||||
self.controller.delete
|
self.controller.delete
|
||||||
self.viewVariant.delete
|
self.viewVariant.delete
|
||||||
self.view.delete
|
self.view.delete
|
||||||
@ -351,6 +356,7 @@ method load*(self: Module) =
|
|||||||
self.buySellCryptoModule.load()
|
self.buySellCryptoModule.load()
|
||||||
self.overviewModule.load()
|
self.overviewModule.load()
|
||||||
self.sendModule.load()
|
self.sendModule.load()
|
||||||
|
self.newSendModule.load()
|
||||||
self.networksModule.load()
|
self.networksModule.load()
|
||||||
self.walletConnectService.init()
|
self.walletConnectService.init()
|
||||||
self.walletConnectController.init()
|
self.walletConnectController.init()
|
||||||
@ -384,6 +390,9 @@ proc checkIfModuleDidLoad(self: Module) =
|
|||||||
if(not self.sendModule.isLoaded()):
|
if(not self.sendModule.isLoaded()):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if(not self.newSendModule.isLoaded()):
|
||||||
|
return
|
||||||
|
|
||||||
if(not self.networksModule.isLoaded()):
|
if(not self.networksModule.isLoaded()):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -432,6 +441,9 @@ method overviewModuleDidLoad*(self: Module) =
|
|||||||
method sendModuleDidLoad*(self: Module) =
|
method sendModuleDidLoad*(self: Module) =
|
||||||
self.checkIfModuleDidLoad()
|
self.checkIfModuleDidLoad()
|
||||||
|
|
||||||
|
method newSendModuleDidLoad*(self: Module) =
|
||||||
|
self.checkIfModuleDidLoad()
|
||||||
|
|
||||||
method networksModuleDidLoad*(self: Module) =
|
method networksModuleDidLoad*(self: Module) =
|
||||||
self.checkIfModuleDidLoad()
|
self.checkIfModuleDidLoad()
|
||||||
|
|
||||||
|
148
src/app/modules/main/wallet_section/send_new/controller.nim
Normal file
148
src/app/modules/main/wallet_section/send_new/controller.nim
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import Tables
|
||||||
|
import uuids, chronicles
|
||||||
|
|
||||||
|
import io_interface
|
||||||
|
|
||||||
|
import app/modules/shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||||
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
import app_service/service/network/service as network_service
|
||||||
|
import app_service/service/transaction/service as transaction_service
|
||||||
|
import app_service/service/keycard/service as keycard_service
|
||||||
|
import app_service/service/network/network_item
|
||||||
|
|
||||||
|
import app/core/eventemitter
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "wallet-send-controller"
|
||||||
|
|
||||||
|
const UNIQUE_WALLET_SECTION_SEND_MODULE_IDENTIFIER* = "WalletSection-NewSendModule"
|
||||||
|
|
||||||
|
type
|
||||||
|
Controller* = ref object of RootObj
|
||||||
|
delegate: io_interface.AccessInterface
|
||||||
|
events: EventEmitter
|
||||||
|
walletAccountService: wallet_account_service.Service
|
||||||
|
networkService: network_service.Service
|
||||||
|
transactionService: transaction_service.Service
|
||||||
|
keycardService: keycard_service.Service
|
||||||
|
connectionKeycardResponse: UUID
|
||||||
|
|
||||||
|
proc newController*(
|
||||||
|
delegate: io_interface.AccessInterface,
|
||||||
|
events: EventEmitter,
|
||||||
|
walletAccountService: wallet_account_service.Service,
|
||||||
|
networkService: network_service.Service,
|
||||||
|
transactionService: transaction_service.Service,
|
||||||
|
keycardService: keycard_service.Service
|
||||||
|
): Controller =
|
||||||
|
result = Controller()
|
||||||
|
result.delegate = delegate
|
||||||
|
result.events = events
|
||||||
|
result.walletAccountService = walletAccountService
|
||||||
|
result.networkService = networkService
|
||||||
|
result.transactionService = transactionService
|
||||||
|
result.keycardService = keycardService
|
||||||
|
|
||||||
|
proc delete*(self: Controller) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc init*(self: Controller) =
|
||||||
|
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
|
||||||
|
let args = TransactionArgs(e)
|
||||||
|
var
|
||||||
|
txHash = ""
|
||||||
|
isApprovalTx = false
|
||||||
|
if not args.sentTransaction.isNil:
|
||||||
|
txHash = args.sentTransaction.hash
|
||||||
|
isApprovalTx = args.sentTransaction.approvalTx
|
||||||
|
self.delegate.transactionWasSent(
|
||||||
|
args.sendDetails.uuid,
|
||||||
|
args.sendDetails.fromChain,
|
||||||
|
isApprovalTx,
|
||||||
|
txHash,
|
||||||
|
if not args.sendDetails.errorResponse.isNil: args.sendDetails.errorResponse.details else: ""
|
||||||
|
)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_OWNER_TOKEN_SENT) do(e:Args):
|
||||||
|
let args = OwnerTokenSentArgs(e)
|
||||||
|
self.delegate.transactionWasSent(args.uuid, args.chainId, approvalTx = false, args.txHash, error = "")
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED) do(e: Args):
|
||||||
|
let args = SharedKeycarModuleArgs(e)
|
||||||
|
if args.uniqueIdentifier != UNIQUE_WALLET_SECTION_SEND_MODULE_IDENTIFIER:
|
||||||
|
return
|
||||||
|
self.delegate.onUserAuthenticated(args.password, args.pin)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_SUGGESTED_ROUTES_READY) do(e:Args):
|
||||||
|
let args = SuggestedRoutesArgs(e)
|
||||||
|
self.delegate.suggestedRoutesReady(args.uuid, args.routes, args.errCode, args.errDescription)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_SIGN_ROUTER_TRANSACTIONS) do(e:Args):
|
||||||
|
var data = RouterTransactionsForSigningArgs(e)
|
||||||
|
self.delegate.prepareSignaturesForTransactions(data.data)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_TRANSACTION_STATUS_CHANGED) do(e:Args):
|
||||||
|
let args = TransactionArgs(e)
|
||||||
|
self.delegate.transactionSendingComplete(args.sentTransaction.hash, args.status)
|
||||||
|
|
||||||
|
proc authenticate*(self: Controller, keyUid = "") =
|
||||||
|
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_WALLET_SECTION_SEND_MODULE_IDENTIFIER,
|
||||||
|
keyUid: keyUid)
|
||||||
|
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
|
||||||
|
|
||||||
|
proc suggestedRoutes*(self: Controller,
|
||||||
|
uuid: string,
|
||||||
|
sendType: SendType,
|
||||||
|
accountFrom: string,
|
||||||
|
accountTo: string,
|
||||||
|
token: string,
|
||||||
|
tokenIsOwnerToken: bool,
|
||||||
|
amountIn: string,
|
||||||
|
toToken: string = "",
|
||||||
|
amountOut: string = "",
|
||||||
|
disabledFromChainIDs: seq[int] = @[],
|
||||||
|
disabledToChainIDs: seq[int] = @[],
|
||||||
|
lockedInAmounts: Table[string, string] = initTable[string, string](),
|
||||||
|
extraParamsTable: Table[string, string] = initTable[string, string]()) =
|
||||||
|
self.transactionService.suggestedRoutes(uuid, sendType, accountFrom, accountTo, token, tokenIsOwnerToken, amountIn, toToken, amountOut,
|
||||||
|
disabledFromChainIDs, disabledToChainIDs, lockedInAmounts, extraParamsTable)
|
||||||
|
|
||||||
|
proc stopSuggestedRoutesAsyncCalculation*(self: Controller) =
|
||||||
|
self.transactionService.stopSuggestedRoutesAsyncCalculation()
|
||||||
|
|
||||||
|
proc getCurrentNetworks*(self: Controller): seq[NetworkItem] =
|
||||||
|
return self.networkService.getCurrentNetworks()
|
||||||
|
|
||||||
|
proc buildTransactionsFromRoute*(self: Controller, uuid: string, slippagePercentage: float): string =
|
||||||
|
return self.transactionService.buildTransactionsFromRoute(uuid, slippagePercentage)
|
||||||
|
|
||||||
|
proc signMessage*(self: Controller, address: string, hashedPassword: string, hashedMessage: string): tuple[res: string, err: string] =
|
||||||
|
return self.transactionService.signMessage(address, hashedPassword, hashedMessage)
|
||||||
|
|
||||||
|
proc sendRouterTransactionsWithSignatures*(self: Controller, uuid: string, signatures: TransactionsSignatures): string =
|
||||||
|
return self.transactionService.sendRouterTransactionsWithSignatures(uuid, signatures)
|
||||||
|
|
||||||
|
proc getKeypairByAccountAddress*(self: Controller, address: string): KeypairDto =
|
||||||
|
return self.walletAccountService.getKeypairByAccountAddress(address)
|
||||||
|
|
||||||
|
proc disconnectKeycardReponseSignal(self: Controller) =
|
||||||
|
self.events.disconnect(self.connectionKeycardResponse)
|
||||||
|
|
||||||
|
proc connectKeycardReponseSignal(self: Controller) =
|
||||||
|
self.connectionKeycardResponse = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
|
||||||
|
let args = KeycardLibArgs(e)
|
||||||
|
self.disconnectKeycardReponseSignal()
|
||||||
|
let currentFlow = self.keycardService.getCurrentFlow()
|
||||||
|
if currentFlow != KCSFlowType.Sign:
|
||||||
|
error "trying to use keycard in the other than the signing a transaction flow"
|
||||||
|
self.delegate.transactionWasSent(uuid = "", chainId = 0, approvalTx = false, txHash = "", error = "trying to use keycard in the other than the signing a transaction flow")
|
||||||
|
return
|
||||||
|
self.delegate.onTransactionSigned(args.flowType, args.flowEvent)
|
||||||
|
|
||||||
|
proc cancelCurrentFlow*(self: Controller) =
|
||||||
|
self.keycardService.cancelCurrentFlow()
|
||||||
|
|
||||||
|
proc runSignFlow*(self: Controller, pin, bip44Path, txHash: string) =
|
||||||
|
self.cancelCurrentFlow()
|
||||||
|
self.connectKeycardReponseSignal()
|
||||||
|
self.keycardService.startSignFlow(bip44Path, txHash, pin)
|
@ -0,0 +1,66 @@
|
|||||||
|
import Tables
|
||||||
|
|
||||||
|
import app_service/service/transaction/dto
|
||||||
|
import app_service/service/transaction/router_transactions_dto
|
||||||
|
import app_service/service/transaction/dtoV2
|
||||||
|
from app_service/service/keycard/service import KeycardEvent
|
||||||
|
|
||||||
|
type
|
||||||
|
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||||
|
## Abstract class for any input/interaction with this module.
|
||||||
|
|
||||||
|
method delete*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method load*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method suggestedRoutes*(self: AccessInterface,
|
||||||
|
uuid: string,
|
||||||
|
sendType: SendType,
|
||||||
|
chainId: int,
|
||||||
|
accountFrom: string,
|
||||||
|
accountTo: string,
|
||||||
|
token: string,
|
||||||
|
tokenIsOwnerToken: bool,
|
||||||
|
amountIn: string,
|
||||||
|
toToken: string = "",
|
||||||
|
amountOut: string = "",
|
||||||
|
extraParamsTable: Table[string, string] = initTable[string, string]()) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method stopUpdatesForSuggestedRoute*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method authenticateAndTransfer*(self: AccessInterface, fromAddr: string, uuid: string, slippagePercentage: float) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onUserAuthenticated*(self: AccessInterface, password: string, pin: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method suggestedRoutesReady*(self: AccessInterface, uuid: string, routes: seq[TransactionPathDtoV2], errCode: string, errDescription: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method transactionWasSent*(self: AccessInterface, uuid: string, chainId: int = 0, approvalTx: bool = false, txHash: string = "", error: string = "") {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method authenticateUser*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onUserAuthenticated*(self: AccessInterface, pin: string, password: string, keyUid: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method prepareSignaturesForTransactions*(self:AccessInterface, txForSigning: RouterTransactionsForSigningDto) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method onTransactionSigned*(self: AccessInterface, keycardFlowType: string, keycardEvent: KeycardEvent) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method transactionSendingComplete*(self: AccessInterface, txHash: string, status: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
@ -0,0 +1,50 @@
|
|||||||
|
import NimQml
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type MaxFeeLevelsItem* = ref object of QObject
|
||||||
|
low: string
|
||||||
|
medium: string
|
||||||
|
high: string
|
||||||
|
|
||||||
|
proc setup*(self: MaxFeeLevelsItem,
|
||||||
|
low: string,
|
||||||
|
medium: string,
|
||||||
|
high: string
|
||||||
|
) =
|
||||||
|
self.QObject.setup
|
||||||
|
self.low = low
|
||||||
|
self.medium = medium
|
||||||
|
self.high = high
|
||||||
|
|
||||||
|
proc delete*(self: MaxFeeLevelsItem) =
|
||||||
|
self.QObject.delete
|
||||||
|
|
||||||
|
proc newMaxFeeLevelsItem*(
|
||||||
|
low: string,
|
||||||
|
medium: string,
|
||||||
|
high: string
|
||||||
|
): MaxFeeLevelsItem =
|
||||||
|
new(result, delete)
|
||||||
|
result.setup(low, medium, high)
|
||||||
|
|
||||||
|
proc `$`*(self: MaxFeeLevelsItem): string =
|
||||||
|
result = "MaxFeeLevelsItem("
|
||||||
|
result = result & "\low: " & $self.low
|
||||||
|
result = result & "\nmedium " & $self.medium
|
||||||
|
result = result & "\nhigh: " & $self.high
|
||||||
|
result = result & ")"
|
||||||
|
|
||||||
|
proc getLow*(self: MaxFeeLevelsItem): string {.slot.} =
|
||||||
|
return self.low
|
||||||
|
QtProperty[string] low:
|
||||||
|
read = getLow
|
||||||
|
|
||||||
|
proc getMedium*(self: MaxFeeLevelsItem): string {.slot.} =
|
||||||
|
return self.medium
|
||||||
|
QtProperty[string] medium:
|
||||||
|
read = getMedium
|
||||||
|
|
||||||
|
proc getHigh*(self: MaxFeeLevelsItem): string {.slot.} =
|
||||||
|
return self.high
|
||||||
|
QtProperty[string] high:
|
||||||
|
read = getHigh
|
314
src/app/modules/main/wallet_section/send_new/module.nim
Normal file
314
src/app/modules/main/wallet_section/send_new/module.nim
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
import tables, NimQml, sequtils, sugar, strutils, chronicles, stint
|
||||||
|
|
||||||
|
import ./io_interface, ./view, ./controller, ./max_fee_levels_item, ./path_item
|
||||||
|
import ../io_interface as delegate_interface
|
||||||
|
|
||||||
|
import app/global/global_singleton
|
||||||
|
import app/core/eventemitter
|
||||||
|
|
||||||
|
import app_service/common/utils
|
||||||
|
import app_service/common/wallet_constants
|
||||||
|
import app_service/service/wallet_account/service as wallet_account_service
|
||||||
|
import app_service/service/network/service as network_service
|
||||||
|
import app_service/service/transaction/service as transaction_service
|
||||||
|
import app_service/service/keycard/service as keycard_service
|
||||||
|
import app_service/service/keycard/constants as keycard_constants
|
||||||
|
import app_service/service/transaction/dto
|
||||||
|
import app_service/service/transaction/dtoV2
|
||||||
|
import app_service/service/token/utils
|
||||||
|
|
||||||
|
export io_interface
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "wallet-send-module"
|
||||||
|
|
||||||
|
const authenticationCanceled* = "authenticationCanceled"
|
||||||
|
|
||||||
|
# Shouldn't be public ever, use only within this module.
|
||||||
|
type TmpSendTransactionDetails = object
|
||||||
|
fromAddrPath: string
|
||||||
|
uuid: string
|
||||||
|
sendType: SendType
|
||||||
|
pin: string
|
||||||
|
password: string
|
||||||
|
txHashBeingProcessed: string
|
||||||
|
resolvedSignatures: TransactionsSignatures
|
||||||
|
slippagePercentage: float
|
||||||
|
|
||||||
|
type
|
||||||
|
Module* = ref object of io_interface.AccessInterface
|
||||||
|
delegate: delegate_interface.AccessInterface
|
||||||
|
events: EventEmitter
|
||||||
|
view: View
|
||||||
|
viewVariant: QVariant
|
||||||
|
controller: controller.Controller
|
||||||
|
moduleLoaded: bool
|
||||||
|
tmpSendTransactionDetails: TmpSendTransactionDetails
|
||||||
|
tmpKeepPinPass: bool
|
||||||
|
|
||||||
|
proc newModule*(
|
||||||
|
delegate: delegate_interface.AccessInterface,
|
||||||
|
events: EventEmitter,
|
||||||
|
walletAccountService: wallet_account_service.Service,
|
||||||
|
networkService: network_service.Service,
|
||||||
|
transactionService: transaction_service.Service,
|
||||||
|
keycardService: keycard_service.Service
|
||||||
|
): Module =
|
||||||
|
result = Module()
|
||||||
|
result.delegate = delegate
|
||||||
|
result.events = events
|
||||||
|
result.controller = controller.newController(result, events, walletAccountService,
|
||||||
|
networkService, transactionService, keycardService)
|
||||||
|
result.view = newView(result)
|
||||||
|
result.viewVariant = newQVariant(result.view)
|
||||||
|
|
||||||
|
result.moduleLoaded = false
|
||||||
|
|
||||||
|
method delete*(self: Module) =
|
||||||
|
self.viewVariant.delete
|
||||||
|
self.view.delete
|
||||||
|
self.controller.delete
|
||||||
|
|
||||||
|
proc clearTmpData(self: Module, keepPinPass = false) =
|
||||||
|
if keepPinPass:
|
||||||
|
self.tmpSendTransactionDetails = TmpSendTransactionDetails(
|
||||||
|
sendType: self.tmpSendTransactionDetails.sendType,
|
||||||
|
pin: self.tmpSendTransactionDetails.pin,
|
||||||
|
password: self.tmpSendTransactionDetails.password
|
||||||
|
)
|
||||||
|
return
|
||||||
|
self.tmpSendTransactionDetails = TmpSendTransactionDetails()
|
||||||
|
|
||||||
|
method load*(self: Module) =
|
||||||
|
singletonInstance.engine.setRootContextProperty("walletSectionSendNew", self.viewVariant)
|
||||||
|
|
||||||
|
self.controller.init()
|
||||||
|
self.view.load()
|
||||||
|
|
||||||
|
method isLoaded*(self: Module): bool =
|
||||||
|
return self.moduleLoaded
|
||||||
|
|
||||||
|
method viewDidLoad*(self: Module) =
|
||||||
|
self.moduleLoaded = true
|
||||||
|
self.delegate.sendModuleDidLoad()
|
||||||
|
|
||||||
|
proc convertFeeLevelsDtoToMaxFeeLevelsItem(self: Module, feeLevels: SuggestedLevelsForMaxFeesPerGasDto): MaxFeeLevelsItem =
|
||||||
|
result = newMaxFeeLevelsItem(
|
||||||
|
low = $feeLevels.low,
|
||||||
|
medium = $feeLevels.medium,
|
||||||
|
high = $feeLevels.high
|
||||||
|
)
|
||||||
|
|
||||||
|
proc convertTransactionPathDtoV2ToPathItem(self: Module, txPath: TransactionPathDtoV2): PathItem =
|
||||||
|
var fromChainId = 0
|
||||||
|
var toChainid = 0
|
||||||
|
var fromTokenSymbol = ""
|
||||||
|
var toTokenSymbol = ""
|
||||||
|
if not txPath.fromChain.isNil:
|
||||||
|
fromChainId = txPath.fromChain.chainId
|
||||||
|
if not txPath.toChain.isNil:
|
||||||
|
toChainId = txPath.toChain.chainId
|
||||||
|
if not txPath.fromToken.isNil:
|
||||||
|
fromTokenSymbol = txPath.fromToken.bySymbolModelKey()
|
||||||
|
if not txPath.toToken.isNil:
|
||||||
|
toTokenSymbol = txPath.toToken.bySymbolModelKey()
|
||||||
|
|
||||||
|
result = newPathItem(
|
||||||
|
processorName = txPath.processorName,
|
||||||
|
fromChain = fromChainId,
|
||||||
|
toChain = toChainId,
|
||||||
|
fromToken = fromTokenSymbol,
|
||||||
|
toToken = toTokenSymbol,
|
||||||
|
amountIn = $txPath.amountIn,
|
||||||
|
amountInLocked = txPath.amountInLocked,
|
||||||
|
amountOut = $txPath.amountOut,
|
||||||
|
suggestedLevelsForMaxFeesPerGas = self.convertFeeLevelsDtoToMaxFeeLevelsItem(txPath.suggestedLevelsForMaxFeesPerGas),
|
||||||
|
maxFeesPerGas = $txPath.maxFeesPerGas,
|
||||||
|
txBaseFee = $txPath.txBaseFee,
|
||||||
|
txPriorityFee = $txPath.txPriorityFee,
|
||||||
|
txGasAmount = $txPath.txGasAmount,
|
||||||
|
txBonderFees = $txPath.txBonderFees,
|
||||||
|
txTokenFees = $txPath.txTokenFees,
|
||||||
|
txFee = $txPath.txFee,
|
||||||
|
txL1Fee = $txPath.txL1Fee,
|
||||||
|
approvalRequired = txPath.approvalRequired,
|
||||||
|
approvalAmountRequired = $txPath.approvalAmountRequired,
|
||||||
|
approvalContractAddress = txPath.approvalContractAddress,
|
||||||
|
approvalBaseFee = $txPath.approvalBaseFee,
|
||||||
|
approvalPriorityFee = $txPath.approvalPriorityFee,
|
||||||
|
approvalGasAmount = $txPath.approvalGasAmount,
|
||||||
|
approvalFee = $txPath.approvalFee,
|
||||||
|
approvalL1Fee = $txPath.approvalL1Fee,
|
||||||
|
txTotalFee = $txPath.txTotalFee,
|
||||||
|
estimatedTime = txPath.estimatedTime
|
||||||
|
)
|
||||||
|
|
||||||
|
proc buildTransactionsFromRoute(self: Module) =
|
||||||
|
let err = self.controller.buildTransactionsFromRoute(self.tmpSendTransactionDetails.uuid, self.tmpSendTransactionDetails.slippagePercentage)
|
||||||
|
if err.len > 0:
|
||||||
|
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = err)
|
||||||
|
self.clearTmpData()
|
||||||
|
|
||||||
|
method authenticateAndTransfer*(self: Module, uuid: string, fromAddr: string, slippagePercentage: float) =
|
||||||
|
self.tmpSendTransactionDetails.uuid = uuid
|
||||||
|
self.tmpSendTransactionDetails.slippagePercentage = slippagePercentage
|
||||||
|
self.tmpSendTransactionDetails.resolvedSignatures.clear()
|
||||||
|
|
||||||
|
if self.tmpKeepPinPass:
|
||||||
|
# no need to authenticate again, just send a swap tx
|
||||||
|
self.buildTransactionsFromRoute()
|
||||||
|
return
|
||||||
|
|
||||||
|
let kp = self.controller.getKeypairByAccountAddress(fromAddr)
|
||||||
|
if kp.migratedToKeycard():
|
||||||
|
let accounts = kp.accounts.filter(acc => cmpIgnoreCase(acc.address, fromAddr) == 0)
|
||||||
|
if accounts.len != 1:
|
||||||
|
error "cannot resolve selected account to send from among known keypair accounts"
|
||||||
|
return
|
||||||
|
self.controller.authenticate(kp.keyUid)
|
||||||
|
else:
|
||||||
|
self.controller.authenticate()
|
||||||
|
|
||||||
|
method onUserAuthenticated*(self: Module, password: string, pin: string) =
|
||||||
|
if password.len == 0:
|
||||||
|
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = authenticationCanceled)
|
||||||
|
self.clearTmpData()
|
||||||
|
else:
|
||||||
|
self.tmpSendTransactionDetails.pin = pin
|
||||||
|
self.tmpSendTransactionDetails.password = password
|
||||||
|
self.buildTransactionsFromRoute()
|
||||||
|
|
||||||
|
proc sendSignedTransactions*(self: Module) =
|
||||||
|
try:
|
||||||
|
# check if all transactions are signed
|
||||||
|
for _, (r, s, v) in self.tmpSendTransactionDetails.resolvedSignatures.pairs:
|
||||||
|
if r.len == 0 or s.len == 0 or v.len == 0:
|
||||||
|
raise newException(CatchableError, "not all transactions are signed")
|
||||||
|
|
||||||
|
let err = self.controller.sendRouterTransactionsWithSignatures(self.tmpSendTransactionDetails.uuid, self.tmpSendTransactionDetails.resolvedSignatures)
|
||||||
|
if err.len > 0:
|
||||||
|
raise newException(CatchableError, "sending transaction failed: " & err)
|
||||||
|
except Exception as e:
|
||||||
|
error "sendSignedTransactions failed: ", msg=e.msg
|
||||||
|
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = e.msg)
|
||||||
|
self.clearTmpData()
|
||||||
|
|
||||||
|
proc signOnKeycard(self: Module) =
|
||||||
|
self.tmpSendTransactionDetails.txHashBeingProcessed = ""
|
||||||
|
for h, (r, s, v) in self.tmpSendTransactionDetails.resolvedSignatures.pairs:
|
||||||
|
if r.len != 0 and s.len != 0 and v.len != 0:
|
||||||
|
continue
|
||||||
|
self.tmpSendTransactionDetails.txHashBeingProcessed = h
|
||||||
|
var txForKcFlow = self.tmpSendTransactionDetails.txHashBeingProcessed
|
||||||
|
if txForKcFlow.startsWith("0x"):
|
||||||
|
txForKcFlow = txForKcFlow[2..^1]
|
||||||
|
self.controller.runSignFlow(self.tmpSendTransactionDetails.pin, self.tmpSendTransactionDetails.fromAddrPath, txForKcFlow)
|
||||||
|
break
|
||||||
|
if self.tmpSendTransactionDetails.txHashBeingProcessed.len == 0:
|
||||||
|
self.sendSignedTransactions()
|
||||||
|
|
||||||
|
proc getRSVFromSignature(self: Module, signature: string): (string, string, string) =
|
||||||
|
let finalSignature = singletonInstance.utils.removeHexPrefix(signature)
|
||||||
|
if finalSignature.len != SIGNATURE_LEN:
|
||||||
|
return ("", "", "")
|
||||||
|
let r = finalSignature[0..63]
|
||||||
|
let s = finalSignature[64..127]
|
||||||
|
let v = finalSignature[128..129]
|
||||||
|
return (r, s, v)
|
||||||
|
|
||||||
|
method prepareSignaturesForTransactions*(self:Module, txForSigning: RouterTransactionsForSigningDto) =
|
||||||
|
var res = ""
|
||||||
|
try:
|
||||||
|
if txForSigning.sendDetails.uuid != self.tmpSendTransactionDetails.uuid:
|
||||||
|
raise newException(CatchableError, "preparing signatures for transactions are not matching the initial request")
|
||||||
|
if txForSigning.signingDetails.hashes.len == 0:
|
||||||
|
raise newException(CatchableError, "no transaction hashes to be signed")
|
||||||
|
if txForSigning.signingDetails.keyUid == "" or txForSigning.signingDetails.address == "" or txForSigning.signingDetails.addressPath == "":
|
||||||
|
raise newException(CatchableError, "preparing signatures for transactions failed")
|
||||||
|
|
||||||
|
if txForSigning.signingDetails.signOnKeycard:
|
||||||
|
self.tmpSendTransactionDetails.fromAddrPath = txForSigning.signingDetails.addressPath
|
||||||
|
for h in txForSigning.signingDetails.hashes:
|
||||||
|
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||||
|
self.signOnKeycard()
|
||||||
|
else:
|
||||||
|
var finalPassword = self.tmpSendTransactionDetails.password
|
||||||
|
if not singletonInstance.userProfile.getIsKeycardUser():
|
||||||
|
finalPassword = hashPassword(self.tmpSendTransactionDetails.password)
|
||||||
|
for h in txForSigning.signingDetails.hashes:
|
||||||
|
self.tmpSendTransactionDetails.resolvedSignatures[h] = ("", "", "")
|
||||||
|
var
|
||||||
|
signature = ""
|
||||||
|
err: string
|
||||||
|
(signature, err) = self.controller.signMessage(txForSigning.signingDetails.address, finalPassword, h)
|
||||||
|
if err.len > 0:
|
||||||
|
raise newException(CatchableError, "signing transaction failed: " & err)
|
||||||
|
self.tmpSendTransactionDetails.resolvedSignatures[h] = self.getRSVFromSignature(signature)
|
||||||
|
self.sendSignedTransactions()
|
||||||
|
except Exception as e:
|
||||||
|
error "signMessageWithCallback failed: ", msg=e.msg
|
||||||
|
self.transactionWasSent(uuid = txForSigning.sendDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = e.msg)
|
||||||
|
self.clearTmpData()
|
||||||
|
|
||||||
|
method onTransactionSigned*(self: Module, keycardFlowType: string, keycardEvent: KeycardEvent) =
|
||||||
|
if keycardFlowType != keycard_constants.ResponseTypeValueKeycardFlowResult:
|
||||||
|
let err = "unexpected error while keycard signing transaction"
|
||||||
|
error "error", err=err
|
||||||
|
self.transactionWasSent(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error = err)
|
||||||
|
self.clearTmpData()
|
||||||
|
return
|
||||||
|
self.tmpSendTransactionDetails.resolvedSignatures[self.tmpSendTransactionDetails.txHashBeingProcessed] = (keycardEvent.txSignature.r,
|
||||||
|
keycardEvent.txSignature.s, keycardEvent.txSignature.v)
|
||||||
|
self.signOnKeycard()
|
||||||
|
|
||||||
|
method transactionWasSent*(self: Module, uuid: string, chainId: int = 0, approvalTx: bool = false, txHash: string = "", error: string = "") =
|
||||||
|
self.tmpKeepPinPass = approvalTx # need to automate the swap flow with approval
|
||||||
|
defer:
|
||||||
|
self.clearTmpData(self.tmpKeepPinPass)
|
||||||
|
if txHash.len == 0:
|
||||||
|
self.view.sendTransactionSentSignal(uuid = self.tmpSendTransactionDetails.uuid, chainId = 0, approvalTx = false, txHash = "", error)
|
||||||
|
return
|
||||||
|
self.view.sendTransactionSentSignal(uuid, chainId, approvalTx, txHash, error)
|
||||||
|
|
||||||
|
method suggestedRoutesReady*(self: Module, uuid: string, routes: seq[TransactionPathDtoV2], errCode: string, errDescription: string) =
|
||||||
|
let paths = routes.map(x => self.convertTransactionPathDtoV2ToPathItem(x))
|
||||||
|
self.view.setTransactionRoute(uuid, paths, errCode, errDescription)
|
||||||
|
|
||||||
|
method suggestedRoutes*(self: Module,
|
||||||
|
uuid: string,
|
||||||
|
sendType: SendType,
|
||||||
|
chainId: int,
|
||||||
|
accountFrom: string,
|
||||||
|
accountTo: string,
|
||||||
|
token: string,
|
||||||
|
tokenIsOwnerToken: bool,
|
||||||
|
amountIn: string,
|
||||||
|
toToken: string = "",
|
||||||
|
amountOut: string = "",
|
||||||
|
extraParamsTable: Table[string, string] = initTable[string, string]()) =
|
||||||
|
# maybe not needed
|
||||||
|
# self.tmpSendTransactionDetails.sendType = sendType
|
||||||
|
var lockedInAmountsTable = Table[string, string] : initTable[string, string]()
|
||||||
|
let networks = self.controller.getCurrentNetworks()
|
||||||
|
let disabledNetworks = networks.filter(x => x.chainId != chainId).map(x => x.chainId)
|
||||||
|
self.controller.suggestedRoutes(
|
||||||
|
uuid,
|
||||||
|
sendType,
|
||||||
|
accountFrom,
|
||||||
|
accountTo,
|
||||||
|
token,
|
||||||
|
tokenIsOwnerToken,
|
||||||
|
amountIn,
|
||||||
|
toToken,
|
||||||
|
amountOut,
|
||||||
|
disabledNetworks,
|
||||||
|
disabledNetworks,
|
||||||
|
lockedInAmountsTable,
|
||||||
|
extraParamsTable
|
||||||
|
)
|
||||||
|
|
||||||
|
method stopUpdatesForSuggestedRoute*(self: Module) =
|
||||||
|
self.controller.stopSuggestedRoutesAsyncCalculation()
|
||||||
|
|
||||||
|
method transactionSendingComplete*(self: Module, txHash: string, status: string) =
|
||||||
|
self.view.sendtransactionSendingCompleteSignal(txHash, status)
|
243
src/app/modules/main/wallet_section/send_new/path_item.nim
Normal file
243
src/app/modules/main/wallet_section/send_new/path_item.nim
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
import NimQml
|
||||||
|
|
||||||
|
import ./max_fee_levels_item
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type PathItem* = ref object of QObject
|
||||||
|
processorName: string
|
||||||
|
fromChain: int
|
||||||
|
toChain: int
|
||||||
|
fromToken: string
|
||||||
|
toToken: string
|
||||||
|
amountIn: string
|
||||||
|
amountInLocked: bool
|
||||||
|
amountOut: string
|
||||||
|
suggestedLevelsForMaxFeesPerGas: MaxFeeLevelsItem
|
||||||
|
maxFeesPerGas: string
|
||||||
|
txBaseFee: string
|
||||||
|
txPriorityFee: string
|
||||||
|
txGasAmount: string
|
||||||
|
txBonderFees: string
|
||||||
|
txTokenFees: string
|
||||||
|
txFee: string
|
||||||
|
txL1Fee: string
|
||||||
|
txTotalFee: string
|
||||||
|
estimatedTime: int
|
||||||
|
approvalRequired: bool
|
||||||
|
approvalAmountRequired : string
|
||||||
|
approvalContractAddress: string
|
||||||
|
approvalBaseFee: string
|
||||||
|
approvalPriorityFee: string
|
||||||
|
approvalGasAmount: string
|
||||||
|
approvalFee: string
|
||||||
|
approvalL1Fee: string
|
||||||
|
|
||||||
|
proc setup*(self: PathItem,
|
||||||
|
processorName: string,
|
||||||
|
fromChain: int,
|
||||||
|
toChain: int,
|
||||||
|
fromToken: string,
|
||||||
|
toToken: string,
|
||||||
|
amountIn: string,
|
||||||
|
amountInLocked: bool,
|
||||||
|
amountOut: string,
|
||||||
|
suggestedLevelsForMaxFeesPerGas: MaxFeeLevelsItem,
|
||||||
|
maxFeesPerGas: string,
|
||||||
|
txBaseFee: string,
|
||||||
|
txPriorityFee: string,
|
||||||
|
txGasAmount: string,
|
||||||
|
txBonderFees: string,
|
||||||
|
txTokenFees: string,
|
||||||
|
txFee: string,
|
||||||
|
txL1Fee: string,
|
||||||
|
txTotalFee: string,
|
||||||
|
estimatedTime: int,
|
||||||
|
approvalRequired: bool,
|
||||||
|
approvalAmountRequired: string,
|
||||||
|
approvalContractAddress: string,
|
||||||
|
approvalBaseFee: string,
|
||||||
|
approvalPriorityFee: string,
|
||||||
|
approvalGasAmount: string,
|
||||||
|
approvalFee: string,
|
||||||
|
approvalL1Fee: string
|
||||||
|
) =
|
||||||
|
self.QObject.setup
|
||||||
|
self.processorName = processorName
|
||||||
|
self.fromChain = fromChain
|
||||||
|
self.toChain = toChain
|
||||||
|
self.fromToken = fromToken
|
||||||
|
self.toToken = toToken
|
||||||
|
self.amountIn = amountIn
|
||||||
|
self.amountInLocked = amountInLocked
|
||||||
|
self.amountOut = amountOut
|
||||||
|
self.suggestedLevelsForMaxFeesPerGas = suggestedLevelsForMaxFeesPerGas
|
||||||
|
self.maxFeesPerGas = maxFeesPerGas
|
||||||
|
self.txBaseFee = txBaseFee
|
||||||
|
self.txPriorityFee = txPriorityFee
|
||||||
|
self.txGasAmount = txGasAmount
|
||||||
|
self.txBonderFees = txBonderFees
|
||||||
|
self.txTokenFees = txTokenFees
|
||||||
|
self.txFee = txFee
|
||||||
|
self.txL1Fee = txL1Fee
|
||||||
|
self.txTotalFee = txTotalFee
|
||||||
|
self.estimatedTime = estimatedTime
|
||||||
|
self.approvalRequired = approvalRequired
|
||||||
|
self.approvalAmountRequired = approvalAmountRequired
|
||||||
|
self.approvalContractAddress = approvalContractAddress
|
||||||
|
self.approvalBaseFee = approvalBaseFee
|
||||||
|
self.approvalPriorityFee = approvalPriorityFee
|
||||||
|
self.approvalGasAmount = approvalGasAmount
|
||||||
|
self.approvalFee = approvalFee
|
||||||
|
self.approvalL1Fee = approvalL1Fee
|
||||||
|
|
||||||
|
proc delete*(self: PathItem) =
|
||||||
|
self.QObject.delete
|
||||||
|
|
||||||
|
proc newPathItem*(
|
||||||
|
processorName: string,
|
||||||
|
fromChain: int,
|
||||||
|
toChain: int,
|
||||||
|
fromToken: string,
|
||||||
|
toToken: string,
|
||||||
|
amountIn: string,
|
||||||
|
amountInLocked: bool,
|
||||||
|
amountOut: string,
|
||||||
|
suggestedLevelsForMaxFeesPerGas: MaxFeeLevelsItem,
|
||||||
|
maxFeesPerGas: string,
|
||||||
|
txBaseFee: string,
|
||||||
|
txPriorityFee: string,
|
||||||
|
txGasAmount: string,
|
||||||
|
txBonderFees: string,
|
||||||
|
txTokenFees: string,
|
||||||
|
txFee: string,
|
||||||
|
txL1Fee: string,
|
||||||
|
txTotalFee: string,
|
||||||
|
estimatedTime: int,
|
||||||
|
approvalRequired: bool,
|
||||||
|
approvalAmountRequired: string,
|
||||||
|
approvalContractAddress: string,
|
||||||
|
approvalBaseFee: string,
|
||||||
|
approvalPriorityFee: string,
|
||||||
|
approvalGasAmount: string,
|
||||||
|
approvalFee: string,
|
||||||
|
approvalL1Fee: string
|
||||||
|
): PathItem =
|
||||||
|
new(result, delete)
|
||||||
|
result.setup(processorName, fromChain, toChain, fromToken, toToken,
|
||||||
|
amountIn, amountInLocked, amountOut, suggestedLevelsForMaxFeesPerGas,
|
||||||
|
maxFeesPerGas, txBaseFee,txPriorityFee, txGasAmount, txBonderFees,
|
||||||
|
txTokenFees, txFee, txL1Fee, txTotalFee, estimatedTime, approvalRequired,
|
||||||
|
approvalAmountRequired, approvalContractAddress, approvalBaseFee,
|
||||||
|
approvalPriorityFee, approvalGasAmount, approvalFee, approvalL1Fee)
|
||||||
|
|
||||||
|
proc `$`*(self: PathItem): string =
|
||||||
|
result = "PathItem("
|
||||||
|
result &= "\nprocessorName: " & $self.processorName
|
||||||
|
result &= "\nfromChain: " & $self.fromChain
|
||||||
|
result &= "\ntoChain: " & $self.toChain
|
||||||
|
result &= "\nfromToken: " & $self.fromToken
|
||||||
|
result &= "\ntoToken: " & $self.toToken
|
||||||
|
result &= "\namountIn: " & $self.amountIn
|
||||||
|
result &= "\namountInLocked: " & $self.amountInLocked
|
||||||
|
result &= "\namountOut: " & $self.amountOut
|
||||||
|
result &= "\nsuggestedLevelsForMaxFeesPerGas: " & $self.suggestedLevelsForMaxFeesPerGas
|
||||||
|
result &= "\nmaxFeesPerGas: " & $self.maxFeesPerGas
|
||||||
|
result &= "\ntxBaseFee: " & $self.txBaseFee
|
||||||
|
result &= "\ntxPriorityFee: " & $self.txPriorityFee
|
||||||
|
result &= "\ntxGasAmount: " & $self.txGasAmount
|
||||||
|
result &= "\ntxBonderFees: " & $self.txBonderFees
|
||||||
|
result &= "\ntxTokenFees: " & $self.txTokenFees
|
||||||
|
result &= "\ntxFee: " & $self.txFee
|
||||||
|
result &= "\ntxL1Fee: " & $self.txL1Fee
|
||||||
|
result &= "\ntxTotalFee: " & $self.txTotalFee
|
||||||
|
result &= "\nestimatedTime: " & $self.estimatedTime
|
||||||
|
result &= "\napprovalRequired: " & $self.approvalRequired
|
||||||
|
result &= "\napprovalAmountRequired: " & $self.approvalAmountRequired
|
||||||
|
result &= "\napprovalContractAddress: " & $self.approvalContractAddress
|
||||||
|
result &= "\napprovalBaseFee: " & $self.approvalBaseFee
|
||||||
|
result &= "\napprovalPriorityFee: " & $self.approvalPriorityFee
|
||||||
|
result &= "\napprovalGasAmount: " & $self.approvalGasAmount
|
||||||
|
result &= "\napprovalFee: " & $self.approvalFee
|
||||||
|
result &= "\napprovalL1Fee: " & $self.approvalL1Fee
|
||||||
|
result &= ")"
|
||||||
|
|
||||||
|
proc processorName*(self: PathItem): string =
|
||||||
|
return self.processorName
|
||||||
|
|
||||||
|
proc fromChain*(self: PathItem): int =
|
||||||
|
return self.fromChain
|
||||||
|
|
||||||
|
proc toChain*(self: PathItem): int =
|
||||||
|
return self.toChain
|
||||||
|
|
||||||
|
proc fromToken*(self: PathItem): string =
|
||||||
|
return self.fromToken
|
||||||
|
|
||||||
|
proc toToken*(self: PathItem): string =
|
||||||
|
return self.toToken
|
||||||
|
|
||||||
|
proc amountIn*(self: PathItem): string =
|
||||||
|
return self.amountIn
|
||||||
|
|
||||||
|
proc amountInLocked*(self: PathItem): bool =
|
||||||
|
return self.amountInLocked
|
||||||
|
|
||||||
|
proc amountOut*(self: PathItem): string =
|
||||||
|
return self.amountOut
|
||||||
|
|
||||||
|
proc suggestedLevelsForMaxFeesPerGas*(self: PathItem): MaxFeeLevelsItem =
|
||||||
|
return self.suggestedLevelsForMaxFeesPerGas
|
||||||
|
|
||||||
|
proc maxFeesPerGas*(self: PathItem): string =
|
||||||
|
return self.maxFeesPerGas
|
||||||
|
|
||||||
|
proc txBaseFee*(self: PathItem): string =
|
||||||
|
return self.txBaseFee
|
||||||
|
|
||||||
|
proc txPriorityFee*(self: PathItem): string =
|
||||||
|
return self.txPriorityFee
|
||||||
|
|
||||||
|
proc txGasAmount*(self: PathItem): string =
|
||||||
|
return self.txGasAmount
|
||||||
|
|
||||||
|
proc txBonderFees*(self: PathItem): string =
|
||||||
|
return self.txBonderFees
|
||||||
|
|
||||||
|
proc txTokenFees*(self: PathItem): string =
|
||||||
|
return self.txTokenFees
|
||||||
|
|
||||||
|
proc txFee*(self: PathItem): string =
|
||||||
|
return self.txFee
|
||||||
|
|
||||||
|
proc txL1Fee*(self: PathItem): string =
|
||||||
|
return self.txL1Fee
|
||||||
|
|
||||||
|
proc txTotalFee*(self: PathItem): string =
|
||||||
|
return self.txTotalFee
|
||||||
|
|
||||||
|
proc estimatedTime*(self: PathItem): int =
|
||||||
|
return self.estimatedTime
|
||||||
|
|
||||||
|
proc approvalRequired*(self: PathItem): bool =
|
||||||
|
return self.approvalRequired
|
||||||
|
|
||||||
|
proc approvalAmountRequired*(self: PathItem): string =
|
||||||
|
return self.approvalAmountRequired
|
||||||
|
|
||||||
|
proc approvalContractAddress*(self: PathItem): string =
|
||||||
|
return self.approvalContractAddress
|
||||||
|
|
||||||
|
proc approvalBaseFee*(self: PathItem): string =
|
||||||
|
return self.approvalBaseFee
|
||||||
|
|
||||||
|
proc approvalPriorityFee*(self: PathItem): string =
|
||||||
|
return self.approvalPriorityFee
|
||||||
|
|
||||||
|
proc approvalGasAmount*(self: PathItem): string =
|
||||||
|
return self.approvalGasAmount
|
||||||
|
|
||||||
|
proc approvalFee*(self: PathItem): string =
|
||||||
|
return self.approvalFee
|
||||||
|
|
||||||
|
proc approvalL1Fee*(self: PathItem): string =
|
||||||
|
return self.approvalL1Fee
|
160
src/app/modules/main/wallet_section/send_new/path_model.nim
Normal file
160
src/app/modules/main/wallet_section/send_new/path_model.nim
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import NimQml, Tables, strutils, stew/shims/strformat
|
||||||
|
|
||||||
|
import ./path_item
|
||||||
|
|
||||||
|
type
|
||||||
|
ModelRole {.pure.} = enum
|
||||||
|
ProcessorName = UserRole + 1,
|
||||||
|
FromChain,
|
||||||
|
ToChain,
|
||||||
|
FromToken,
|
||||||
|
ToToken,
|
||||||
|
AmountIn,
|
||||||
|
AmountInLocked,
|
||||||
|
AmountOut,
|
||||||
|
SuggestedLevelsForMaxFeesPerGas,
|
||||||
|
MaxFeesPerGas,
|
||||||
|
TxBaseFee,
|
||||||
|
TxPriorityFee,
|
||||||
|
TxGasAmount,
|
||||||
|
TxBonderFees,
|
||||||
|
TxTokenFees,
|
||||||
|
TxFee,
|
||||||
|
TxL1Fee,
|
||||||
|
TxTotalFee,
|
||||||
|
EstimatedTime,
|
||||||
|
ApprovalRequired,
|
||||||
|
ApprovalAmountRequired,
|
||||||
|
ApprovalContractAddress,
|
||||||
|
ApprovalBaseFee,
|
||||||
|
ApprovalPriorityFee,
|
||||||
|
ApprovalGasAmount,
|
||||||
|
ApprovalFee,
|
||||||
|
ApprovalL1Fee
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
PathModel* = ref object of QAbstractListModel
|
||||||
|
items*: seq[PathItem]
|
||||||
|
|
||||||
|
proc delete(self: PathModel) =
|
||||||
|
self.items = @[]
|
||||||
|
self.QAbstractListModel.delete
|
||||||
|
|
||||||
|
proc setup(self: PathModel) =
|
||||||
|
self.QAbstractListModel.setup
|
||||||
|
|
||||||
|
proc newPathModel*(): PathModel =
|
||||||
|
new(result, delete)
|
||||||
|
result.setup
|
||||||
|
|
||||||
|
proc `$`*(self: PathModel): string =
|
||||||
|
for i in 0 ..< self.items.len:
|
||||||
|
result &= fmt"""[{i}]:({$self.items[i]})"""
|
||||||
|
|
||||||
|
method rowCount(self: PathModel, index: QModelIndex = nil): int =
|
||||||
|
return self.items.len
|
||||||
|
|
||||||
|
method roleNames(self: PathModel): Table[int, string] =
|
||||||
|
{
|
||||||
|
ModelRole.ProcessorName.int: "processorName",
|
||||||
|
ModelRole.FromChain.int: "fromChain",
|
||||||
|
ModelRole.ToChain.int: "toChain",
|
||||||
|
ModelRole.FromToken.int: "fromToken",
|
||||||
|
ModelRole.ToToken.int: "toToken",
|
||||||
|
ModelRole.AmountIn.int: "amountIn",
|
||||||
|
ModelRole.AmountInLocked.int: "amountInLocked",
|
||||||
|
ModelRole.AmountOut.int: "amountOut",
|
||||||
|
ModelRole.SuggestedLevelsForMaxFeesPerGas.int: "suggestedLevelsForMaxFeesPerGas",
|
||||||
|
ModelRole.MaxFeesPerGas.int: "maxFeesPerGas",
|
||||||
|
ModelRole.TxBaseFee.int: "txBaseFee",
|
||||||
|
ModelRole.TxPriorityFee.int: "txPriorityFee",
|
||||||
|
ModelRole.TxGasAmount.int: "txGasAmount",
|
||||||
|
ModelRole.TxBonderFees.int: "txBonderFees",
|
||||||
|
ModelRole.TxTokenFees.int: "txTokenFees",
|
||||||
|
ModelRole.TxFee.int: "txFee",
|
||||||
|
ModelRole.TxL1Fee.int: "txL1Fee",
|
||||||
|
ModelRole.TxTotalFee.int: "txTotalFee",
|
||||||
|
ModelRole.EstimatedTime.int: "estimatedTime",
|
||||||
|
ModelRole.ApprovalRequired.int: "approvalRequired",
|
||||||
|
ModelRole.ApprovalAmountRequired.int: "approvalAmountRequired",
|
||||||
|
ModelRole.ApprovalContractAddress.int: "approvalContractAddress",
|
||||||
|
ModelRole.ApprovalBaseFee.int: "approvalBaseFee",
|
||||||
|
ModelRole.ApprovalPriorityFee.int: "approvalPriorityFee",
|
||||||
|
ModelRole.ApprovalGasAmount.int: "approvalGasAmount",
|
||||||
|
ModelRole.ApprovalFee.int: "approvalFee",
|
||||||
|
ModelRole.ApprovalL1Fee.int: "approvalL1Fee",
|
||||||
|
}.toTable
|
||||||
|
|
||||||
|
proc setItems*(self: PathModel, items: seq[PathItem]) =
|
||||||
|
self.beginResetModel()
|
||||||
|
self.items = items
|
||||||
|
self.endResetModel()
|
||||||
|
|
||||||
|
method data(self: PathModel, index: QModelIndex, role: int): QVariant =
|
||||||
|
if (not index.isValid):
|
||||||
|
return
|
||||||
|
|
||||||
|
if (index.row < 0 or index.row >= self.items.len):
|
||||||
|
return
|
||||||
|
|
||||||
|
let item = self.items[index.row]
|
||||||
|
let enumRole = role.ModelRole
|
||||||
|
|
||||||
|
case enumRole:
|
||||||
|
of ModelRole.ProcessorName:
|
||||||
|
result = newQVariant(item.processorName)
|
||||||
|
of ModelRole.FromChain:
|
||||||
|
result = newQVariant(item.fromChain)
|
||||||
|
of ModelRole.ToChain:
|
||||||
|
result = newQVariant(item.toChain)
|
||||||
|
of ModelRole.FromToken:
|
||||||
|
result = newQVariant(item.fromToken)
|
||||||
|
of ModelRole.ToToken:
|
||||||
|
result = newQVariant(item.toToken)
|
||||||
|
of ModelRole.AmountIn:
|
||||||
|
result = newQVariant(item.amountIn)
|
||||||
|
of ModelRole.AmountInLocked:
|
||||||
|
result = newQVariant(item.amountInLocked)
|
||||||
|
of ModelRole.AmountOut:
|
||||||
|
result = newQVariant(item.amountOut)
|
||||||
|
of ModelRole.SuggestedLevelsForMaxFeesPerGas:
|
||||||
|
result = newQVariant(item.suggestedLevelsForMaxFeesPerGas)
|
||||||
|
of ModelRole.MaxFeesPerGas:
|
||||||
|
result = newQVariant(item.maxFeesPerGas)
|
||||||
|
of ModelRole.TxBaseFee:
|
||||||
|
result = newQVariant(item.txBaseFee)
|
||||||
|
of ModelRole.TxPriorityFee:
|
||||||
|
result = newQVariant(item.txPriorityFee)
|
||||||
|
of ModelRole.TxGasAmount:
|
||||||
|
result = newQVariant(item.txGasAmount)
|
||||||
|
of ModelRole.TxBonderFees:
|
||||||
|
result = newQVariant(item.txBonderFees)
|
||||||
|
of ModelRole.TxTokenFees:
|
||||||
|
result = newQVariant(item.txTokenFees)
|
||||||
|
of ModelRole.TxFee:
|
||||||
|
result = newQVariant(item.txFee)
|
||||||
|
of ModelRole.TxL1Fee:
|
||||||
|
result = newQVariant(item.txL1Fee)
|
||||||
|
of ModelRole.TxTotalFee:
|
||||||
|
result = newQVariant(item.txTotalFee)
|
||||||
|
of ModelRole.EstimatedTime:
|
||||||
|
result = newQVariant(item.estimatedTime)
|
||||||
|
of ModelRole.ApprovalRequired:
|
||||||
|
result = newQVariant(item.approvalRequired)
|
||||||
|
of ModelRole.ApprovalAmountRequired:
|
||||||
|
result = newQVariant(item.approvalAmountRequired)
|
||||||
|
of ModelRole.ApprovalContractAddress:
|
||||||
|
result = newQVariant(item.approvalContractAddress)
|
||||||
|
of ModelRole.ApprovalBaseFee:
|
||||||
|
result = newQVariant(item.approvalBaseFee)
|
||||||
|
of ModelRole.ApprovalPriorityFee:
|
||||||
|
result = newQVariant(item.approvalPriorityFee)
|
||||||
|
of ModelRole.ApprovalGasAmount:
|
||||||
|
result = newQVariant(item.approvalGasAmount)
|
||||||
|
of ModelRole.ApprovalFee:
|
||||||
|
result = newQVariant(item.approvalFee)
|
||||||
|
of ModelRole.ApprovalL1Fee:
|
||||||
|
result = newQVariant(item.approvalL1Fee)
|
||||||
|
else:
|
||||||
|
discard
|
88
src/app/modules/main/wallet_section/send_new/view.nim
Normal file
88
src/app/modules/main/wallet_section/send_new/view.nim
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import NimQml, Tables, json, sequtils, strutils, stint, chronicles
|
||||||
|
|
||||||
|
import ./io_interface, ./path_model, ./path_item
|
||||||
|
import app_service/common/utils as common_utils
|
||||||
|
import app_service/service/eth/utils as eth_utils
|
||||||
|
import app_service/service/transaction/dto as transaction_dto
|
||||||
|
from backend/eth import ExtraKeyPackId
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
View* = ref object of QObject
|
||||||
|
delegate: io_interface.AccessInterface
|
||||||
|
pathModel: PathModel
|
||||||
|
|
||||||
|
proc delete*(self: View) =
|
||||||
|
self.pathModel.delete
|
||||||
|
self.QObject.delete
|
||||||
|
|
||||||
|
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||||
|
new(result, delete)
|
||||||
|
result.QObject.setup
|
||||||
|
result.delegate = delegate
|
||||||
|
result.pathModel = newPathModel()
|
||||||
|
|
||||||
|
proc load*(self: View) =
|
||||||
|
self.delegate.viewDidLoad()
|
||||||
|
|
||||||
|
proc fetchSuggestedRoutes*(self: View,
|
||||||
|
uuid: string,
|
||||||
|
sendType: int,
|
||||||
|
chainId: int,
|
||||||
|
accountFrom: string,
|
||||||
|
accountTo: string,
|
||||||
|
amountIn: string,
|
||||||
|
token: string,
|
||||||
|
amountOut: string,
|
||||||
|
toToken: string,
|
||||||
|
extraParamsJson: string) {.slot.} =
|
||||||
|
var extraParamsTable: Table[string, string]
|
||||||
|
self.pathModel.setItems(@[])
|
||||||
|
try:
|
||||||
|
if extraParamsJson.len > 0:
|
||||||
|
for key, value in parseJson(extraParamsJson):
|
||||||
|
if key == ExtraKeyPackId:
|
||||||
|
let bigPackId = common_utils.stringToUint256(value.getStr())
|
||||||
|
let packIdHex = "0x" & eth_utils.stripLeadingZeros(bigPackId.toHex)
|
||||||
|
extraParamsTable[key] = packIdHex
|
||||||
|
else:
|
||||||
|
extraParamsTable[key] = value.getStr()
|
||||||
|
except Exception as e:
|
||||||
|
error "Error parsing extraParamsJson: ", msg=e.msg
|
||||||
|
|
||||||
|
self.delegate.suggestedRoutes(
|
||||||
|
uuid,
|
||||||
|
SendType(sendType),
|
||||||
|
chainId,
|
||||||
|
accountFrom,
|
||||||
|
accountTo,
|
||||||
|
token,
|
||||||
|
false, #tokenIsOwnerToken
|
||||||
|
amountIn,
|
||||||
|
toToken,
|
||||||
|
amountOut,
|
||||||
|
extraParamsTable)
|
||||||
|
|
||||||
|
proc stopUpdatesForSuggestedRoute*(self: View) {.slot.} =
|
||||||
|
self.delegate.stopUpdatesForSuggestedRoute()
|
||||||
|
|
||||||
|
proc authenticateAndTransfer*(self: View, uuid: string, fromAddr: string, slippagePercentageString: string) {.slot.} =
|
||||||
|
var slippagePercentage: float
|
||||||
|
try:
|
||||||
|
slippagePercentage = slippagePercentageString.parseFloat()
|
||||||
|
except:
|
||||||
|
error "parsing slippage failed", slippage=slippagePercentageString
|
||||||
|
self.delegate.authenticateAndTransfer(uuid, fromAddr, slippagePercentage)
|
||||||
|
|
||||||
|
proc suggestedRoutesReady*(self: View, uuid: string, pathModel: QVariant, errCode: string, errDescription: string) {.signal.}
|
||||||
|
proc setTransactionRoute*(self: View, uuid: string, paths: seq[PathItem], errCode: string, errDescription: string) =
|
||||||
|
self.pathModel.setItems(paths)
|
||||||
|
self.suggestedRoutesReady(uuid, newQVariant(self.pathModel), errCode, errDescription)
|
||||||
|
|
||||||
|
proc transactionSendingComplete*(self: View, txHash: string, status: string) {.signal.}
|
||||||
|
proc sendtransactionSendingCompleteSignal*(self: View, txHash: string, status: string) =
|
||||||
|
self.transactionSendingComplete(txHash, status)
|
||||||
|
|
||||||
|
proc transactionSent*(self: View, uuid: string, chainId: int, approvalTx: bool, txHash: string, error: string) {.signal.}
|
||||||
|
proc sendTransactionSentSignal*(self: View, uuid: string, chainId: int, approvalTx: bool, txHash: string, error: string) =
|
||||||
|
self.transactionSent(uuid, chainId, approvalTx, txHash, error)
|
@ -30,11 +30,13 @@ type
|
|||||||
amountInLocked*: bool
|
amountInLocked*: bool
|
||||||
amountOut*: UInt256
|
amountOut*: UInt256
|
||||||
suggestedLevelsForMaxFeesPerGas*: SuggestedLevelsForMaxFeesPerGasDto
|
suggestedLevelsForMaxFeesPerGas*: SuggestedLevelsForMaxFeesPerGasDto
|
||||||
|
maxFeesPerGas*: UInt256
|
||||||
txBaseFee*: UInt256
|
txBaseFee*: UInt256
|
||||||
txPriorityFee*: UInt256
|
txPriorityFee*: UInt256
|
||||||
txGasAmount*: uint64
|
txGasAmount*: uint64
|
||||||
txBonderFees*: UInt256
|
txBonderFees*: UInt256
|
||||||
txTokenFees*: UInt256
|
txTokenFees*: UInt256
|
||||||
|
txFee*: UInt256
|
||||||
txL1Fee*: UInt256
|
txL1Fee*: UInt256
|
||||||
approvalRequired*: bool
|
approvalRequired*: bool
|
||||||
approvalAmountRequired*: UInt256
|
approvalAmountRequired*: UInt256
|
||||||
@ -42,7 +44,9 @@ type
|
|||||||
approvalBaseFee*: UInt256
|
approvalBaseFee*: UInt256
|
||||||
approvalPriorityFee*: UInt256
|
approvalPriorityFee*: UInt256
|
||||||
approvalGasAmount*: uint64
|
approvalGasAmount*: uint64
|
||||||
|
approvalFee*: UInt256
|
||||||
approvalL1Fee*: UInt256
|
approvalL1Fee*: UInt256
|
||||||
|
txTotalFee*: UInt256
|
||||||
estimatedTime*: int
|
estimatedTime*: int
|
||||||
|
|
||||||
proc toSuggestedLevelsForMaxFeesPerGasDto*(jsonObj: JsonNode): SuggestedLevelsForMaxFeesPerGasDto =
|
proc toSuggestedLevelsForMaxFeesPerGasDto*(jsonObj: JsonNode): SuggestedLevelsForMaxFeesPerGasDto =
|
||||||
@ -66,11 +70,13 @@ proc toTransactionPathDtoV2*(jsonObj: JsonNode): TransactionPathDtoV2 =
|
|||||||
discard jsonObj.getProp("AmountInLocked", result.amountInLocked)
|
discard jsonObj.getProp("AmountInLocked", result.amountInLocked)
|
||||||
result.amountOut = stint.fromHex(UInt256, jsonObj{"AmountOut"}.getStr)
|
result.amountOut = stint.fromHex(UInt256, jsonObj{"AmountOut"}.getStr)
|
||||||
result.suggestedLevelsForMaxFeesPerGas = jsonObj["SuggestedLevelsForMaxFeesPerGas"].toSuggestedLevelsForMaxFeesPerGasDto()
|
result.suggestedLevelsForMaxFeesPerGas = jsonObj["SuggestedLevelsForMaxFeesPerGas"].toSuggestedLevelsForMaxFeesPerGasDto()
|
||||||
|
result.maxFeesPerGas = stint.fromHex(UInt256, jsonObj{"MaxFeesPerGas"}.getStr)
|
||||||
result.txBaseFee = stint.fromHex(UInt256, jsonObj{"TxBaseFee"}.getStr)
|
result.txBaseFee = stint.fromHex(UInt256, jsonObj{"TxBaseFee"}.getStr)
|
||||||
result.txPriorityFee = stint.fromHex(UInt256, jsonObj{"TxPriorityFee"}.getStr)
|
result.txPriorityFee = stint.fromHex(UInt256, jsonObj{"TxPriorityFee"}.getStr)
|
||||||
discard jsonObj.getProp("TxGasAmount", result.txGasAmount)
|
discard jsonObj.getProp("TxGasAmount", result.txGasAmount)
|
||||||
result.txBonderFees = stint.fromHex(UInt256, jsonObj{"TxBonderFees"}.getStr)
|
result.txBonderFees = stint.fromHex(UInt256, jsonObj{"TxBonderFees"}.getStr)
|
||||||
result.txTokenFees = stint.fromHex(UInt256, jsonObj{"TxTokenFees"}.getStr)
|
result.txTokenFees = stint.fromHex(UInt256, jsonObj{"TxTokenFees"}.getStr)
|
||||||
|
result.txFee = stint.fromHex(UInt256, jsonObj{"TxFee"}.getStr)
|
||||||
result.txL1Fee = stint.fromHex(UInt256, jsonObj{"TxL1Fee"}.getStr)
|
result.txL1Fee = stint.fromHex(UInt256, jsonObj{"TxL1Fee"}.getStr)
|
||||||
discard jsonObj.getProp("ApprovalRequired", result.approvalRequired)
|
discard jsonObj.getProp("ApprovalRequired", result.approvalRequired)
|
||||||
result.approvalAmountRequired = stint.fromHex(UInt256, jsonObj{"ApprovalAmountRequired"}.getStr)
|
result.approvalAmountRequired = stint.fromHex(UInt256, jsonObj{"ApprovalAmountRequired"}.getStr)
|
||||||
@ -78,7 +84,9 @@ proc toTransactionPathDtoV2*(jsonObj: JsonNode): TransactionPathDtoV2 =
|
|||||||
result.approvalBaseFee = stint.fromHex(UInt256, jsonObj{"ApprovalBaseFee"}.getStr)
|
result.approvalBaseFee = stint.fromHex(UInt256, jsonObj{"ApprovalBaseFee"}.getStr)
|
||||||
result.approvalPriorityFee = stint.fromHex(UInt256, jsonObj{"ApprovalPriorityFee"}.getStr)
|
result.approvalPriorityFee = stint.fromHex(UInt256, jsonObj{"ApprovalPriorityFee"}.getStr)
|
||||||
discard jsonObj.getProp("ApprovalGasAmount", result.approvalGasAmount)
|
discard jsonObj.getProp("ApprovalGasAmount", result.approvalGasAmount)
|
||||||
|
result.approvalFee = stint.fromHex(UInt256, jsonObj{"ApprovalFee"}.getStr)
|
||||||
result.approvalL1Fee = stint.fromHex(UInt256, jsonObj{"ApprovalL1Fee"}.getStr)
|
result.approvalL1Fee = stint.fromHex(UInt256, jsonObj{"ApprovalL1Fee"}.getStr)
|
||||||
|
result.txTotalFee = stint.fromHex(UInt256, jsonObj{"TxTotalFee"}.getStr)
|
||||||
result.estimatedTime = jsonObj{"EstimatedTime"}.getInt
|
result.estimatedTime = jsonObj{"EstimatedTime"}.getInt
|
||||||
|
|
||||||
proc toTransactionPathsDtoV2*(jsonObj: JsonNode): seq[TransactionPathDtoV2] =
|
proc toTransactionPathsDtoV2*(jsonObj: JsonNode): seq[TransactionPathDtoV2] =
|
||||||
|
@ -115,6 +115,8 @@ type
|
|||||||
SuggestedRoutesArgs* = ref object of Args
|
SuggestedRoutesArgs* = ref object of Args
|
||||||
uuid*: string
|
uuid*: string
|
||||||
suggestedRoutes*: SuggestedRoutesDto
|
suggestedRoutes*: SuggestedRoutesDto
|
||||||
|
# this should be the only one used when old send modal code is removed
|
||||||
|
routes*: seq[TransactionPathDtoV2]
|
||||||
errCode*: string
|
errCode*: string
|
||||||
errDescription*: string
|
errDescription*: string
|
||||||
|
|
||||||
@ -362,6 +364,7 @@ QtObject:
|
|||||||
self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(
|
self.events.emit(SIGNAL_SUGGESTED_ROUTES_READY, SuggestedRoutesArgs(
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
suggestedRoutes: suggestedDto,
|
suggestedRoutes: suggestedDto,
|
||||||
|
routes: route,
|
||||||
errCode: errCode,
|
errCode: errCode,
|
||||||
errDescription: errDescription
|
errDescription: errDescription
|
||||||
))
|
))
|
||||||
|
@ -62,6 +62,7 @@ SplitView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
property var setFees: Backpressure.debounce(root, 1500, function () {
|
property var setFees: Backpressure.debounce(root, 1500, function () {
|
||||||
|
simpleSend.routesLoading = false
|
||||||
simpleSend.estimatedTime = "~60s"
|
simpleSend.estimatedTime = "~60s"
|
||||||
simpleSend.estimatedFiatFees = "1.45 EUR"
|
simpleSend.estimatedFiatFees = "1.45 EUR"
|
||||||
simpleSend.estimatedCryptoFees = "0.0007 ETH"
|
simpleSend.estimatedCryptoFees = "0.0007 ETH"
|
||||||
@ -125,8 +126,9 @@ SplitView {
|
|||||||
estimatedCryptoFees = ""
|
estimatedCryptoFees = ""
|
||||||
estimatedFiatFees = ""
|
estimatedFiatFees = ""
|
||||||
estimatedTime = ""
|
estimatedTime = ""
|
||||||
if(formCorrectlyFilled) {
|
if(allValuesFilledCorrectly) {
|
||||||
console.log("Fetch fees...")
|
console.log("Fetch fees...")
|
||||||
|
routesLoading = true
|
||||||
d.setFees()
|
d.setFees()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ Control {
|
|||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
loading: root.loading
|
loading: root.loading || !root.cryptoFees
|
||||||
customColor: root.error ? Theme.palette.dangerColor1:
|
customColor: root.error ? Theme.palette.dangerColor1:
|
||||||
Theme.palette.baseColor1
|
Theme.palette.baseColor1
|
||||||
lineHeightMode: Text.FixedHeight
|
lineHeightMode: Text.FixedHeight
|
||||||
@ -79,7 +79,7 @@ Control {
|
|||||||
|
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
loading: root.loading
|
loading: root.loading || !root.fiatFees
|
||||||
customColor: root.error ? Theme.palette.dangerColor1:
|
customColor: root.error ? Theme.palette.dangerColor1:
|
||||||
Theme.palette.baseColor1
|
Theme.palette.baseColor1
|
||||||
lineHeightMode: Text.FixedHeight
|
lineHeightMode: Text.FixedHeight
|
||||||
|
@ -72,8 +72,7 @@ StatusDialog {
|
|||||||
Only networks valid as per mainnet/testnet selection
|
Only networks valid as per mainnet/testnet selection
|
||||||
**/
|
**/
|
||||||
required property var networksModel
|
required property var networksModel
|
||||||
required property var savedAddressesModel
|
|
||||||
required property var recentRecipientsModel
|
|
||||||
/** Input property holds currently selected Fiat currency **/
|
/** Input property holds currently selected Fiat currency **/
|
||||||
required property string currentCurrency
|
required property string currentCurrency
|
||||||
/** Input function to format currency amount to locale string **/
|
/** Input function to format currency amount to locale string **/
|
||||||
@ -82,6 +81,9 @@ StatusDialog {
|
|||||||
/** input property to decide if send modal is interactive or prefilled **/
|
/** input property to decide if send modal is interactive or prefilled **/
|
||||||
property bool interactive: true
|
property bool interactive: true
|
||||||
|
|
||||||
|
/** input property to decide if routes are being fetched **/
|
||||||
|
property bool routesLoading
|
||||||
|
|
||||||
/** input property to set estimated time **/
|
/** input property to set estimated time **/
|
||||||
property string estimatedTime
|
property string estimatedTime
|
||||||
/** input property to set estimated fees in fiat **/
|
/** input property to set estimated fees in fiat **/
|
||||||
@ -89,6 +91,8 @@ StatusDialog {
|
|||||||
/** input property to set estimated fees in crypto **/
|
/** input property to set estimated fees in crypto **/
|
||||||
property string estimatedCryptoFees
|
property string estimatedCryptoFees
|
||||||
|
|
||||||
|
/** property to set currently selected send type **/
|
||||||
|
property int sendType: Constants.SendType.Transfer
|
||||||
/** property to set and expose currently selected account **/
|
/** property to set and expose currently selected account **/
|
||||||
property string selectedAccountAddress
|
property string selectedAccountAddress
|
||||||
/** property to set and expose currently selected network **/
|
/** property to set and expose currently selected network **/
|
||||||
@ -102,11 +106,19 @@ StatusDialog {
|
|||||||
e.g. 1000000000000000000 for 1 ETH **/
|
e.g. 1000000000000000000 for 1 ETH **/
|
||||||
readonly property string selectedAmountInBaseUnit: amountToSend.amount
|
readonly property string selectedAmountInBaseUnit: amountToSend.amount
|
||||||
|
|
||||||
/** property to scheck if form has been filled correctly **/
|
/** property to check if the form is filled correctly **/
|
||||||
readonly property bool formCorrectlyFilled: d.allValuesFilledCorrectly()
|
readonly property bool allValuesFilledCorrectly: !!root.selectedAccountAddress &&
|
||||||
|
root.selectedChainId !== 0 &&
|
||||||
|
!!root.selectedTokenKey &&
|
||||||
|
!!root.selectedRecipientAddress &&
|
||||||
|
!!root.selectedAmount &&
|
||||||
|
!amountToSend.markAsInvalid &&
|
||||||
|
amountToSend.valid
|
||||||
|
|
||||||
/** TODO: replace with new and improved recipient selector StatusDateRangePicker
|
/** TODO: replace with new and improved recipient selector StatusDateRangePicker
|
||||||
TBD under https://github.com/status-im/status-desktop/issues/16916 **/
|
TBD under https://github.com/status-im/status-desktop/issues/16916 **/
|
||||||
|
required property var savedAddressesModel
|
||||||
|
required property var recentRecipientsModel
|
||||||
property alias selectedRecipientAddress: recipientsPanel.selectedRecipientAddress
|
property alias selectedRecipientAddress: recipientsPanel.selectedRecipientAddress
|
||||||
/** Input function to resolve Ens Name **/
|
/** Input function to resolve Ens Name **/
|
||||||
required property var fnResolveENS
|
required property var fnResolveENS
|
||||||
@ -207,30 +219,14 @@ StatusDialog {
|
|||||||
return WalletUtils.calculateMaxSafeSendAmount(maxCryptoBalance, d.selectedCryptoTokenSymbol)
|
return WalletUtils.calculateMaxSafeSendAmount(maxCryptoBalance, d.selectedCryptoTokenSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
function allValuesFilledCorrectly() {
|
|
||||||
return !!root.selectedAccountAddress &&
|
|
||||||
root.selectedChainId !== 0 &&
|
|
||||||
!!root.selectedTokenKey &&
|
|
||||||
!!root.selectedRecipientAddress &&
|
|
||||||
!!root.selectedAmount &&
|
|
||||||
!amountToSend.markAsInvalid &&
|
|
||||||
amountToSend.valid
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle multiple property changes from single changed signal
|
// handle multiple property changes from single changed signal
|
||||||
property var combinedPropertyChangedHandler: [
|
property var combinedPropertyChangedHandler: [
|
||||||
root.selectedAccountAddress,
|
root.selectedAccountAddress,
|
||||||
root.selectedChainId,
|
root.selectedChainId,
|
||||||
root.selectedTokenKey,
|
root.selectedTokenKey,
|
||||||
root.selectedRecipientAddress,
|
root.selectedRecipientAddress,
|
||||||
root.selectedAmount,
|
root.selectedAmount]
|
||||||
amountToSend.markAsInvalid,
|
|
||||||
amountToSend.valid]
|
|
||||||
onCombinedPropertyChangedHandlerChanged: Qt.callLater(() => root.formChanged())
|
onCombinedPropertyChangedHandlerChanged: Qt.callLater(() => root.formChanged())
|
||||||
|
|
||||||
readonly property bool feesIsLoading: !root.estimatedCryptoFees &&
|
|
||||||
!root.estimatedFiatFees &&
|
|
||||||
!root.estimatedTime
|
|
||||||
}
|
}
|
||||||
|
|
||||||
width: 556
|
width: 556
|
||||||
@ -467,9 +463,9 @@ StatusDialog {
|
|||||||
|
|
||||||
cryptoFees: root.estimatedCryptoFees
|
cryptoFees: root.estimatedCryptoFees
|
||||||
fiatFees: root.estimatedFiatFees
|
fiatFees: root.estimatedFiatFees
|
||||||
loading: d.feesIsLoading && d.allValuesFilledCorrectly()
|
loading: root.routesLoading && root.allValuesFilledCorrectly
|
||||||
}
|
}
|
||||||
visible: d.allValuesFilledCorrectly()
|
visible: root.allValuesFilledCorrectly
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -481,7 +477,7 @@ StatusDialog {
|
|||||||
estimatedTime: root.estimatedTime
|
estimatedTime: root.estimatedTime
|
||||||
estimatedFees: root.estimatedFiatFees
|
estimatedFees: root.estimatedFiatFees
|
||||||
|
|
||||||
loading: d.feesIsLoading && d.allValuesFilledCorrectly()
|
loading: root.routesLoading && root.allValuesFilledCorrectly
|
||||||
|
|
||||||
onReviewSendClicked: root.reviewSendClicked()
|
onReviewSendClicked: root.reviewSendClicked()
|
||||||
}
|
}
|
||||||
|
33
ui/app/AppLayouts/Wallet/stores/TransactionStoreNew.qml
Normal file
33
ui/app/AppLayouts/Wallet/stores/TransactionStoreNew.qml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var _walletSectionSendInst: walletSectionSendNew
|
||||||
|
|
||||||
|
signal suggestedRoutesReady(string uuid, var pathModel, string errCode, string errDescription)
|
||||||
|
signal transactionSent(string uuid, int chainId, bool approvalTx, string txHash, string error)
|
||||||
|
|
||||||
|
function authenticateAndTransfer(uuid, fromAddr, slippagePercentage = "") {
|
||||||
|
_walletSectionSendInst.authenticateAndTransfer(uuid, fromAddr, slippagePercentage)
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchSuggestedRoutes(uuid, sendType, chainId, accountFrom,
|
||||||
|
accountTo, amountIn, token,
|
||||||
|
amountOut = "0", toToken = "",
|
||||||
|
extraParamsJson = "") {
|
||||||
|
_walletSectionSendInst.fetchSuggestedRoutes(uuid, sendType, chainId, accountFrom,
|
||||||
|
accountTo, amountIn, token,
|
||||||
|
amountOut, toToken, extraParamsJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopUpdatesForSuggestedRoute() {
|
||||||
|
_walletSectionSendInst.stopUpdatesForSuggestedRoute()
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
_walletSectionSendInst.suggestedRoutesReady.connect(suggestedRoutesReady)
|
||||||
|
_walletSectionSendInst.transactionSent.connect(transactionSent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,3 +5,4 @@ TokensStore 1.0 TokensStore.qml
|
|||||||
WalletAssetsStore 1.0 WalletAssetsStore.qml
|
WalletAssetsStore 1.0 WalletAssetsStore.qml
|
||||||
SwapStore 1.0 SwapStore.qml
|
SwapStore 1.0 SwapStore.qml
|
||||||
BuyCryptoStore 1.0 BuyCryptoStore.qml
|
BuyCryptoStore 1.0 BuyCryptoStore.qml
|
||||||
|
TransactionStoreNew 1.0 TransactionStoreNew.qml
|
||||||
|
@ -102,6 +102,8 @@ Item {
|
|||||||
paymentRequestEnabled: featureFlags ? featureFlags.paymentRequestEnabled : false
|
paymentRequestEnabled: featureFlags ? featureFlags.paymentRequestEnabled : false
|
||||||
simpleSendEnabled: featureFlags ? featureFlags.simpleSendEnabled : false
|
simpleSendEnabled: featureFlags ? featureFlags.simpleSendEnabled : false
|
||||||
}
|
}
|
||||||
|
// TODO: Only until the old send modal transaction store can be replaced with this one
|
||||||
|
readonly property WalletStores.TransactionStoreNew transactionStoreNew: WalletStores.TransactionStoreNew {}
|
||||||
|
|
||||||
required property bool isCentralizedMetricsEnabled
|
required property bool isCentralizedMetricsEnabled
|
||||||
|
|
||||||
@ -646,6 +648,7 @@ Item {
|
|||||||
loginType: appMain.rootStore.loginType
|
loginType: appMain.rootStore.loginType
|
||||||
transactionStore: appMain.transactionStore
|
transactionStore: appMain.transactionStore
|
||||||
walletCollectiblesStore: appMain.walletCollectiblesStore
|
walletCollectiblesStore: appMain.walletCollectiblesStore
|
||||||
|
transactionStoreNew: appMain.transactionStoreNew
|
||||||
|
|
||||||
// for ens flows
|
// for ens flows
|
||||||
ensRegisteredAddress: appMain.rootStore.profileSectionStore.ensUsernamesStore.getEnsRegisteredAddress()
|
ensRegisteredAddress: appMain.rootStore.profileSectionStore.ensUsernamesStore.getEnsRegisteredAddress()
|
||||||
@ -668,6 +671,7 @@ Item {
|
|||||||
currentCurrency: appMain.currencyStore.currentCurrency
|
currentCurrency: appMain.currencyStore.currentCurrency
|
||||||
showCommunityAssetsInSend: appMain.tokensStore.showCommunityAssetsInSend
|
showCommunityAssetsInSend: appMain.tokensStore.showCommunityAssetsInSend
|
||||||
collectiblesBySymbolModel: WalletStores.RootStore.collectiblesStore.jointCollectiblesBySymbolModel
|
collectiblesBySymbolModel: WalletStores.RootStore.collectiblesStore.jointCollectiblesBySymbolModel
|
||||||
|
tokenBySymbolModel: appMain.tokensStore.plainTokensBySymbolModel
|
||||||
fnFormatCurrencyAmount: function(amount, symbol, options = null, locale = null) {
|
fnFormatCurrencyAmount: function(amount, symbol, options = null, locale = null) {
|
||||||
return appMain.currencyStore.formatCurrencyAmount(amount, symbol)
|
return appMain.currencyStore.formatCurrencyAmount(amount, symbol)
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,14 @@ import QtQuick 2.15
|
|||||||
|
|
||||||
import SortFilterProxyModel 0.2
|
import SortFilterProxyModel 0.2
|
||||||
|
|
||||||
|
import StatusQ 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||||
|
|
||||||
import AppLayouts.Wallet.stores 1.0 as WalletStores
|
import AppLayouts.Wallet.stores 1.0 as WalletStores
|
||||||
import AppLayouts.Wallet.popups.simpleSend 1.0
|
import AppLayouts.Wallet.popups.simpleSend 1.0
|
||||||
import AppLayouts.Wallet.adaptors 1.0
|
import AppLayouts.Wallet.adaptors 1.0
|
||||||
|
import AppLayouts.Wallet 1.0
|
||||||
|
|
||||||
import shared.popups.send 1.0
|
import shared.popups.send 1.0
|
||||||
import shared.stores.send 1.0
|
import shared.stores.send 1.0
|
||||||
@ -21,6 +23,7 @@ QtObject {
|
|||||||
required property int loginType
|
required property int loginType
|
||||||
required property TransactionStore transactionStore
|
required property TransactionStore transactionStore
|
||||||
required property WalletStores.CollectiblesStore walletCollectiblesStore
|
required property WalletStores.CollectiblesStore walletCollectiblesStore
|
||||||
|
required property WalletStores.TransactionStoreNew transactionStoreNew
|
||||||
|
|
||||||
/** for ens flows **/
|
/** for ens flows **/
|
||||||
required property string myPublicKey
|
required property string myPublicKey
|
||||||
@ -73,6 +76,13 @@ QtObject {
|
|||||||
- accountAddress [string] - unique identifier of an account
|
- accountAddress [string] - unique identifier of an account
|
||||||
**/
|
**/
|
||||||
required property var collectiblesBySymbolModel
|
required property var collectiblesBySymbolModel
|
||||||
|
/** Expected model structure:
|
||||||
|
- key [string] - unique identifier of an asset
|
||||||
|
- decimals [int] - decimals of the token
|
||||||
|
- marketDetails [QObject] - collectible's contract address
|
||||||
|
- currencyPrice [CurrencyAmount] - assets market price in CurrencyAmount
|
||||||
|
**/
|
||||||
|
required property var tokenBySymbolModel
|
||||||
/**
|
/**
|
||||||
Expected model structure:
|
Expected model structure:
|
||||||
- chainId: network chain id
|
- chainId: network chain id
|
||||||
@ -236,65 +246,148 @@ QtObject {
|
|||||||
/** TODO: use the newly defined WalletAccountsSelectorAdaptor
|
/** TODO: use the newly defined WalletAccountsSelectorAdaptor
|
||||||
in https://github.com/status-im/status-desktop/pull/16834 **/
|
in https://github.com/status-im/status-desktop/pull/16834 **/
|
||||||
accountsModel: root.walletAccountsModel
|
accountsModel: root.walletAccountsModel
|
||||||
assetsModel: assetsSelectorViewAdaptor.outputAssetsModel
|
assetsModel: backendHandler.assetsSelectorViewAdaptor.outputAssetsModel
|
||||||
collectiblesModel: collectiblesSelectionAdaptor.model
|
collectiblesModel: backendHandler.collectiblesSelectionAdaptor.model
|
||||||
networksModel: root.filteredFlatNetworksModel
|
networksModel: backendHandler.filteredFlatNetworksModel
|
||||||
|
|
||||||
savedAddressesModel: root.savedAddressesModel
|
savedAddressesModel: root.savedAddressesModel
|
||||||
recentRecipientsModel: root.recentRecipientsModel
|
recentRecipientsModel: root.recentRecipientsModel
|
||||||
|
|
||||||
currentCurrency: root.currentCurrency
|
currentCurrency: root.currentCurrency
|
||||||
fnFormatCurrencyAmount: root.fnFormatCurrencyAmount
|
fnFormatCurrencyAmount: root.fnFormatCurrencyAmount
|
||||||
fnResolveENS: root.fnResolveENS
|
fnResolveENS: root.fnResolveENS
|
||||||
|
|
||||||
onClosed: destroy()
|
onClosed: {
|
||||||
|
destroy()
|
||||||
|
root.transactionStoreNew.stopUpdatesForSuggestedRoute()
|
||||||
|
}
|
||||||
|
|
||||||
onFormChanged: {
|
onFormChanged: {
|
||||||
estimatedCryptoFees = ""
|
estimatedCryptoFees = ""
|
||||||
estimatedFiatFees = ""
|
estimatedFiatFees = ""
|
||||||
estimatedTime = ""
|
estimatedTime = ""
|
||||||
if(formCorrectlyFilled) {
|
if(allValuesFilledCorrectly) {
|
||||||
// TODO: call stores fetchSuggestedRoutes api
|
backendHandler.uuid = Utils.uuid()
|
||||||
|
simpleSendModal.routesLoading = true
|
||||||
|
root.transactionStoreNew.fetchSuggestedRoutes(backendHandler.uuid,
|
||||||
|
sendType,
|
||||||
|
selectedChainId,
|
||||||
|
selectedAccountAddress,
|
||||||
|
selectedRecipientAddress,
|
||||||
|
selectedAmountInBaseUnit,
|
||||||
|
selectedTokenKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenSelectorViewAdaptor {
|
// TODO: this should be called from the Reiew and Sign Modal instead
|
||||||
id: assetsSelectorViewAdaptor
|
onReviewSendClicked: {
|
||||||
|
root.transactionStoreNew.authenticateAndTransfer(uuid, selectedAccountAddress)
|
||||||
// TODO: remove all store dependecies and add specific properties to the handler instead
|
|
||||||
assetsModel: root.groupedAccountAssetsModel
|
|
||||||
flatNetworksModel: root.flatNetworksModel
|
|
||||||
|
|
||||||
currentCurrency: root.currentCurrency
|
|
||||||
showCommunityAssets: root.showCommunityAssetsInSend
|
|
||||||
|
|
||||||
accountAddress: simpleSendModal.selectedAccountAddress
|
|
||||||
enabledChainIds: [simpleSendModal.selectedChainId]
|
|
||||||
}
|
}
|
||||||
CollectiblesSelectionAdaptor {
|
|
||||||
id: collectiblesSelectionAdaptor
|
|
||||||
|
|
||||||
accountKey: simpleSendModal.selectedAccountAddress
|
readonly property var backendHandler: QtObject {
|
||||||
enabledChainIds: [simpleSendModal.selectedChainId]
|
property string uuid
|
||||||
|
property var fetchedPathModel
|
||||||
|
|
||||||
networksModel: root.filteredFlatNetworksModel
|
readonly property var filteredFlatNetworksModel: SortFilterProxyModel {
|
||||||
collectiblesModel: SortFilterProxyModel {
|
sourceModel: root.flatNetworksModel
|
||||||
sourceModel: root.collectiblesBySymbolModel
|
filters: ValueFilter { roleName: "isTest"; value: root.areTestNetworksEnabled }
|
||||||
filters: ValueFilter {
|
}
|
||||||
roleName: "soulbound"
|
|
||||||
value: false
|
function routesFetched(returnedUuid, pathModel, errCode, errDescription) {
|
||||||
|
simpleSendModal.routesLoading = false
|
||||||
|
if(returnedUuid !== uuid) {
|
||||||
|
// Suggested routes for a different fetch, ignore
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fetchedPathModel = pathModel
|
||||||
|
}
|
||||||
|
|
||||||
|
function transactionSent(returnedUuid, chainId, approvalTx, txHash, error) {
|
||||||
|
if(returnedUuid !== uuid) {
|
||||||
|
// Suggested routes for a different fetch, ignore
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!!error) {
|
||||||
|
if (error.includes(Constants.walletSection.authenticationCanceled)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO: handle error here
|
||||||
|
return
|
||||||
|
}
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var assetsSelectorViewAdaptor: TokenSelectorViewAdaptor {
|
||||||
|
// TODO: remove all store dependecies and add specific properties to the handler instead
|
||||||
|
assetsModel: root.groupedAccountAssetsModel
|
||||||
|
flatNetworksModel: root.flatNetworksModel
|
||||||
|
|
||||||
|
currentCurrency: root.currentCurrency
|
||||||
|
showCommunityAssets: root.showCommunityAssetsInSend
|
||||||
|
|
||||||
|
accountAddress: simpleSendModal.selectedAccountAddress
|
||||||
|
enabledChainIds: [simpleSendModal.selectedChainId]
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var collectiblesSelectionAdaptor: CollectiblesSelectionAdaptor {
|
||||||
|
accountKey: simpleSendModal.selectedAccountAddress
|
||||||
|
enabledChainIds: [simpleSendModal.selectedChainId]
|
||||||
|
|
||||||
|
networksModel: backendHandler.filteredFlatNetworksModel
|
||||||
|
collectiblesModel: SortFilterProxyModel {
|
||||||
|
sourceModel: root.collectiblesBySymbolModel
|
||||||
|
filters: ValueFilter {
|
||||||
|
roleName: "soulbound"
|
||||||
|
value: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
readonly property var totalBalanceAggregator: FunctionAggregator {
|
||||||
root.ensNameResolved.connect(ensNameResolved)
|
model: !!backendHandler.fetchedPathModel ?
|
||||||
|
backendHandler.fetchedPathModel: null
|
||||||
|
initialValue: "0"
|
||||||
|
roleName: "txTotalFee"
|
||||||
|
|
||||||
|
aggregateFunction: (aggr, value) => SQUtils.AmountsArithmetic.sum(
|
||||||
|
SQUtils.AmountsArithmetic.fromString(aggr),
|
||||||
|
SQUtils.AmountsArithmetic.fromString(value)).toString()
|
||||||
|
|
||||||
|
onValueChanged: {
|
||||||
|
let decimals = !!backendHandler.ethTokenEntry.item ? backendHandler.ethTokenEntry.item.decimals: 18
|
||||||
|
let ethFiatValue = !!backendHandler.ethTokenEntry.item ? backendHandler.ethTokenEntry.item.marketDetails.currencyPrice.amount: 1
|
||||||
|
let totalFees = SQUtils.AmountsArithmetic.div(SQUtils.AmountsArithmetic.fromString(value), SQUtils.AmountsArithmetic.fromNumber(1, decimals))
|
||||||
|
let totalFeesInFiat = root.fnFormatCurrencyAmount(ethFiatValue*totalFees, root.currentCurrency).toString()
|
||||||
|
simpleSendModal.estimatedCryptoFees = root.fnFormatCurrencyAmount(totalFees.toString(), Constants.ethToken)
|
||||||
|
simpleSendModal.estimatedFiatFees = totalFeesInFiat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var estimatedTimeAggregator: SumAggregator {
|
||||||
|
model: !!backendHandler.fetchedPathModel ?
|
||||||
|
backendHandler.fetchedPathModel: null
|
||||||
|
roleName: "estimatedTime"
|
||||||
|
onValueChanged: {
|
||||||
|
simpleSendModal.estimatedTime = WalletUtils.getLabelForEstimatedTxTime(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var selectedTokenEntry: ModelEntry {
|
||||||
|
sourceModel: root.tokenBySymbolModel
|
||||||
|
key: "key"
|
||||||
|
value: simpleSendModal.selectedTokenKey
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property var ethTokenEntry: ModelEntry {
|
||||||
|
sourceModel: root.tokenBySymbolModel
|
||||||
|
key: "key"
|
||||||
|
value: Constants.ethToken
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.ensNameResolved.connect(ensNameResolved)
|
||||||
|
root.transactionStoreNew.suggestedRoutesReady.connect(routesFetched)
|
||||||
|
root.transactionStoreNew.transactionSent.connect(transactionSent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var filteredFlatNetworksModel: SortFilterProxyModel {
|
|
||||||
sourceModel: root.flatNetworksModel
|
|
||||||
filters: ValueFilter { roleName: "isTest"; value: root.areTestNetworksEnabled }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user