fix: checksum validation (#15915)
* feat: checksum validation added to adding saved addresses Fixes: #15772 * feat: checksum validation added to adding watch only address Fixes: #15779
This commit is contained in:
parent
63076e6ecc
commit
7dc08731f4
|
@ -71,3 +71,6 @@ proc hasPairedDevices*(self: Controller): bool =
|
|||
|
||||
proc reloadAccountTokens*(self: Controller) =
|
||||
self.walletAccountService.reloadAccountTokens()
|
||||
|
||||
proc isChecksumValidForAddress*(self: Controller, address: string): bool =
|
||||
return self.walletAccountService.isChecksumValidForAddress(address)
|
|
@ -123,3 +123,6 @@ method canProfileProveOwnershipOfProvidedAddresses*(self: AccessInterface, addre
|
|||
|
||||
method reloadAccountTokens*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isChecksumValidForAddress*(self: AccessInterface, address: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -539,3 +539,6 @@ method canProfileProveOwnershipOfProvidedAddresses*(self: Module, addresses: str
|
|||
method reloadAccountTokens*(self: Module) =
|
||||
self.view.setIsAccountTokensReloading(true)
|
||||
self.controller.reloadAccountTokens()
|
||||
|
||||
method isChecksumValidForAddress*(self: Module, address: string): bool =
|
||||
return self.controller.isChecksumValidForAddress(address)
|
|
@ -300,7 +300,7 @@ QtObject:
|
|||
QtProperty[QVariant] lastReloadTimestamp:
|
||||
read = getLastReloadTimestamp
|
||||
notify = lastReloadTimestampChanged
|
||||
|
||||
|
||||
proc isAccountTokensReloadingChanged*(self: View) {.signal.}
|
||||
|
||||
proc setIsAccountTokensReloading*(self: View, isAccountTokensReloading: bool) =
|
||||
|
@ -316,3 +316,5 @@ QtObject:
|
|||
read = getIsAccountTokensReloading
|
||||
notify = isAccountTokensReloadingChanged
|
||||
|
||||
proc isChecksumValidForAddress*(self: View, address: string): bool {.slot.} =
|
||||
return self.delegate.isChecksumValidForAddress(address)
|
|
@ -252,6 +252,9 @@ proc getNumOfAddressesToGenerateForKeypair*(self: Controller, keyUid: string): i
|
|||
proc resolveSuggestedPathForKeypair*(self: Controller, keyUid: string): string =
|
||||
return self.walletAccountService.resolveSuggestedPathForKeypair(keyUid)
|
||||
|
||||
proc isChecksumValidForAddress*(self: Controller, address: string): bool =
|
||||
return self.walletAccountService.isChecksumValidForAddress(address)
|
||||
|
||||
proc remainingAccountCapacity*(self: Controller): int =
|
||||
return self.walletAccountService.remainingAccountCapacity()
|
||||
|
||||
|
@ -259,4 +262,4 @@ proc remainingKeypairCapacity*(self: Controller): int =
|
|||
return self.walletAccountService.remainingKeypairCapacity()
|
||||
|
||||
proc remainingWatchOnlyAccountCapacity*(self: Controller): int =
|
||||
return self.walletAccountService.remainingWatchOnlyAccountCapacity()
|
||||
return self.walletAccountService.remainingWatchOnlyAccountCapacity()
|
|
@ -107,6 +107,9 @@ method removingSavedAddressConfirmed*(self: AccessInterface, address: string) {.
|
|||
method savedAddressDeleted*(self: AccessInterface, address: string, errorMsg: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isChecksumValidForAddress*(self: AccessInterface, address: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method remainingAccountCapacity*(self: AccessInterface): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -736,6 +736,9 @@ method buildNewSeedPhraseKeypairAndAddItToOrigin*[T](self: Module[T]) =
|
|||
derivedFrom = genAcc.address)
|
||||
self.setItemForSelectedOrigin(item)
|
||||
|
||||
method isChecksumValidForAddress*[T](self: Module[T], address: string): bool =
|
||||
return self.controller.isChecksumValidForAddress(address)
|
||||
|
||||
method remainingAccountCapacity*[T](self: Module[T]): int =
|
||||
return self.controller.remainingAccountCapacity()
|
||||
|
||||
|
|
|
@ -364,6 +364,9 @@ QtObject:
|
|||
proc removingSavedAddressRejected*(self: View) {.slot.} =
|
||||
self.setDisablePopup(false)
|
||||
|
||||
proc isChecksumValidForAddress*(self: View, address: string): bool {.slot.} =
|
||||
return self.delegate.isChecksumValidForAddress(address)
|
||||
|
||||
proc remainingAccountCapacity*(self: View): int {.slot.} =
|
||||
return self.delegate.remainingAccountCapacity()
|
||||
|
||||
|
|
|
@ -92,6 +92,17 @@ QtObject:
|
|||
result.networkService = networkService
|
||||
result.currencyService = currencyService
|
||||
|
||||
proc isChecksumValidForAddress*(self: Service, address: string): bool =
|
||||
var updated = false
|
||||
try:
|
||||
let response = backend.isChecksumValidForAddress(address)
|
||||
if not response.error.isNil:
|
||||
error "status-go error", procName="isChecksumValidForAddress", errCode=response.error.code, errDesription=response.error.message
|
||||
return response.result.getBool
|
||||
except Exception as e:
|
||||
error "error: ", procName="isChecksumValidForAddress", errName=e.name, errDesription=e.msg
|
||||
|
||||
|
||||
include service_account
|
||||
include service_token
|
||||
include service_keycard
|
||||
|
|
|
@ -332,3 +332,6 @@ rpc(getBalancesByChain, "wallet"):
|
|||
|
||||
rpc(restartWalletReloadTimer, "wallet"):
|
||||
discard
|
||||
|
||||
rpc(isChecksumValidForAddress, "wallet"):
|
||||
address: string
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
StatusIcon {
|
||||
id: root
|
||||
|
||||
property string tooltipText
|
||||
|
||||
MouseArea {
|
||||
id: tooltipSensor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: tooltipSensor.containsMouse && !!text
|
||||
text: root.tooltipText
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ StatusCenteredFlow 0.1 StatusCenteredFlow.qml
|
|||
StatusFontSettings 0.1 StatusFontSettings.qml
|
||||
StatusGridView 0.1 StatusGridView.qml
|
||||
StatusIcon 0.1 StatusIcon.qml
|
||||
StatusIconWithTooltip 0.1 StatusIconWithTooltip.qml
|
||||
StatusIdenticonRingSettings 0.1 StatusIdenticonRingSettings.qml
|
||||
StatusListView 0.1 StatusListView.qml
|
||||
StatusModalHeaderSettings 0.1 StatusModalHeaderSettings.qml
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
<file>StatusQ/Core/StatusFontSettings.qml</file>
|
||||
<file>StatusQ/Core/StatusGridView.qml</file>
|
||||
<file>StatusQ/Core/StatusIcon.qml</file>
|
||||
<file>StatusQ/Core/StatusIconWithTooltip.qml</file>
|
||||
<file>StatusQ/Core/StatusIdenticonRingSettings.qml</file>
|
||||
<file>StatusQ/Core/StatusListView.qml</file>
|
||||
<file>StatusQ/Core/StatusModalHeaderSettings.qml</file>
|
||||
|
|
|
@ -102,7 +102,7 @@ StatusModal {
|
|||
property bool chainShortNamesDirty: false
|
||||
property var networkSelection: []
|
||||
|
||||
onNetworkSelectionChanged: {
|
||||
onNetworkSelectionChanged: {
|
||||
if (d.networkSelection !== networkSelectPopup.selection) {
|
||||
networkSelectPopup.selection = d.networkSelection
|
||||
}
|
||||
|
@ -119,6 +119,8 @@ StatusModal {
|
|||
|| chainShortNamesDirty && (!d.editMode || d.storedChainShortNames !== d.chainShortNames)
|
||||
|| d.colorId.toUpperCase() !== d.storedColorId.toUpperCase()
|
||||
|
||||
property bool incorrectChecksum: false
|
||||
|
||||
|
||||
readonly property var chainPrefixRegexPattern: /[^:]+\:?|:/g
|
||||
readonly property bool addressInputIsENS: !!d.ens &&
|
||||
|
@ -231,6 +233,13 @@ StatusModal {
|
|||
addressInput.errorMessageCmp.visible = true
|
||||
}
|
||||
|
||||
function checkIfAddressChecksumIsValid() {
|
||||
d.incorrectChecksum = false
|
||||
if (d.addressInputIsAddress) {
|
||||
d.incorrectChecksum = !root.store.isChecksumValidForAddress(d.address)
|
||||
}
|
||||
}
|
||||
|
||||
function checkForAddressInputErrorsWarnings() {
|
||||
addressInput.errorMessageCmp.visible = false
|
||||
addressInput.errorMessageCmp.color = Theme.palette.dangerColor1
|
||||
|
@ -261,6 +270,7 @@ StatusModal {
|
|||
networkSelector.state = ""
|
||||
if (d.addressInputIsAddress) {
|
||||
d.checkForAddressInputOwningErrorsWarnings()
|
||||
d.checkIfAddressChecksumIsValid()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -453,7 +463,7 @@ StatusModal {
|
|||
enabled: !(d.editMode || d.addAddress)
|
||||
input.edit.textFormat: TextEdit.RichText
|
||||
input.rightComponent: (d.resolvingEnsNameInProgress || d.checkingContactsAddressInProgress) ?
|
||||
loadingIndicator : null
|
||||
loadingIndicator : d.incorrectChecksum? incorrectChecksumComponent : null
|
||||
input.asset.name: d.addressInputValid && !d.editMode ? "checkbox" : ""
|
||||
input.asset.color: enabled ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
|
||||
input.asset.width: 17
|
||||
|
@ -472,6 +482,18 @@ StatusModal {
|
|||
StatusLoadingIndicator {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: incorrectChecksumComponent
|
||||
|
||||
StatusIconWithTooltip {
|
||||
icon: "warning"
|
||||
width: 20
|
||||
height: 20
|
||||
color: Theme.palette.warningColor1
|
||||
tooltipText: qsTr("Checksum of the entered address is incorrect")
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
if (skipTextUpdate || !d.initialized)
|
||||
return
|
||||
|
@ -503,7 +525,7 @@ StatusModal {
|
|||
d.ens = ""
|
||||
d.address = prefixAndAddress.address
|
||||
d.chainShortNames = prefixAndAddress.prefix
|
||||
|
||||
|
||||
Qt.callLater(()=> {
|
||||
// Sync chain short names with model. This could result in removing networks from this text
|
||||
// Call it later to avoid binding loop warnings
|
||||
|
|
|
@ -304,6 +304,10 @@ QtObject {
|
|||
}
|
||||
}
|
||||
|
||||
function isChecksumValidForAddress(address) {
|
||||
return root.walletSectionInst.isChecksumValidForAddress(address)
|
||||
}
|
||||
|
||||
function getNameForAddress(address) {
|
||||
var name = getNameForWalletAddress(address)
|
||||
if (name.length === 0) {
|
||||
|
|
|
@ -20,6 +20,16 @@ Column {
|
|||
addressInput.reset()
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
property bool incorrectChecksum: false
|
||||
|
||||
function checkIfAddressChecksumIsValid(address) {
|
||||
d.incorrectChecksum = !root.store.isChecksumValidForAddress(address)
|
||||
}
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: addressInput
|
||||
objectName: "AddAccountPopup-WatchOnlyAddress"
|
||||
|
@ -29,14 +39,27 @@ Column {
|
|||
label: qsTr("Ethereum address or ENS name")
|
||||
placeholderText: qsTr("Type or paste ETH address")
|
||||
input.multiline: true
|
||||
input.rightComponent: StatusButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
borderColor: Theme.palette.primaryColor1
|
||||
size: StatusBaseButton.Size.Tiny
|
||||
text: qsTr("Paste")
|
||||
onClicked: {
|
||||
addressInput.text = ""
|
||||
addressInput.input.edit.paste()
|
||||
input.rightComponent: Row {
|
||||
spacing: 8
|
||||
|
||||
StatusIconWithTooltip {
|
||||
visible: d.incorrectChecksum
|
||||
icon: "warning"
|
||||
width: 20
|
||||
height: 20
|
||||
color: Theme.palette.warningColor1
|
||||
tooltipText: qsTr("Checksum of the entered address is incorrect")
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
borderColor: Theme.palette.primaryColor1
|
||||
size: StatusBaseButton.Size.Tiny
|
||||
text: qsTr("Paste")
|
||||
onClicked: {
|
||||
addressInput.text = ""
|
||||
addressInput.input.edit.paste()
|
||||
}
|
||||
}
|
||||
}
|
||||
validators: [
|
||||
|
@ -46,8 +69,11 @@ Column {
|
|||
]
|
||||
|
||||
onTextChanged: {
|
||||
d.incorrectChecksum = false
|
||||
if (addressInput.valid) {
|
||||
root.store.changeWatchOnlyAccountAddressPostponed(text.trim())
|
||||
const trimmedText = text.trim()
|
||||
root.store.changeWatchOnlyAccountAddressPostponed(trimmedText)
|
||||
d.checkIfAddressChecksumIsValid(trimmedText)
|
||||
return
|
||||
}
|
||||
root.store.cleanWatchOnlyAccountAddress()
|
||||
|
|
|
@ -167,6 +167,10 @@ BasePopupStore {
|
|||
root.addAccountModule.startScanningForActivity()
|
||||
}
|
||||
|
||||
function isChecksumValidForAddress(address) {
|
||||
return root.addAccountModule.isChecksumValidForAddress(address)
|
||||
}
|
||||
|
||||
function remainingAccountCapacity() {
|
||||
return root.addAccountModule.remainingAccountCapacity()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue