feat: release ENS names

This commit is contained in:
Richard Ramos 2021-08-09 18:23:52 -04:00 committed by Iuri Matias
parent ef1140d0a7
commit 80343446ec
11 changed files with 387 additions and 74 deletions

View File

@ -11,7 +11,7 @@ import ../../../status/wallet
import sets import sets
import web3/ethtypes import web3/ethtypes
import ../../../status/tasks/[qt, task_runner_impl] import ../../../status/tasks/[qt, task_runner_impl]
import chronicles
type type
EnsRoles {.pure.} = enum EnsRoles {.pure.} = enum
UserName = UserRole + 1 UserName = UserRole + 1
@ -45,11 +45,21 @@ const detailsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
arg = decode[DetailsTaskArg](argEncoded) arg = decode[DetailsTaskArg](argEncoded)
address = status_ens.address(arg.username) address = status_ens.address(arg.username)
pubkey = status_ens.pubkey(arg.username) pubkey = status_ens.pubkey(arg.username)
json = %* {
"ensName": arg.username, var isStatus:bool = false
"address": address, var expirationTime:int = 0
"pubkey": pubkey if arg.username.endsWith(domain):
} isStatus = true
var success = false
expirationTime = status_ens.getExpirationTime(arg.username.replace(domain, ""), success)
let json = %* {
"ensName": arg.username,
"address": address,
"pubkey": pubkey,
"isStatus": isStatus,
"expirationTime": expirationTime
}
arg.finish(json) arg.finish(json)
proc details[T](self: T, slot: string, username: string) = proc details[T](self: T, slot: string, username: string) =
@ -87,8 +97,9 @@ QtObject:
let pendingTransactions = self.status.wallet.getPendingTransactions() let pendingTransactions = self.status.wallet.getPendingTransactions()
if (pendingTransactions == ""): if (pendingTransactions == ""):
return return
for trx in pendingTransactions.parseJson{"result"}.getElems(): for trx in pendingTransactions.parseJson{"result"}.getElems():
if trx["type"].getStr == $PendingTransactionType.RegisterENS: if trx["type"].getStr == $PendingTransactionType.RegisterENS or trx["type"].getStr == $PendingTransactionType.SetPubKey:
self.usernames.add trx["additionalData"].getStr self.usernames.add trx["additionalData"].getStr
self.pendingUsernames.incl trx["additionalData"].getStr self.pendingUsernames.incl trx["additionalData"].getStr
@ -106,6 +117,19 @@ QtObject:
self.usernames.add(username) self.usernames.add(username)
self.endInsertRows() self.endInsertRows()
proc remove*(self: EnsManager, username: string) =
var idx = -1
var i = 0
for u in self.usernames:
if u == username:
idx = i
break
i = i + 1
if idx == -1: return
self.beginRemoveRows(newQModelIndex(), idx, idx)
self.usernames.delete(idx)
self.endRemoveRows()
proc getPreferredUsername(self: EnsManager): string {.slot.} = proc getPreferredUsername(self: EnsManager): string {.slot.} =
result = self.status.settings.getSetting[:string](Setting.PreferredUsername, "") result = self.status.settings.getSetting[:string](Setting.PreferredUsername, "")
@ -138,12 +162,12 @@ QtObject:
self.loading(true) self.loading(true)
self.details("setDetails", username) self.details("setDetails", username)
proc detailsObtained(self: EnsManager, ensName: string, address: string, pubkey: string) {.signal.} proc detailsObtained(self: EnsManager, ensName: string, address: string, pubkey: string, isStatus: bool, expirationTime: int) {.signal.}
proc setDetails(self: EnsManager, details: string): string {.slot.} = proc setDetails(self: EnsManager, details: string): string {.slot.} =
self.loading(false) self.loading(false)
let detailsJson = details.parseJson let detailsJson = details.parseJson
self.detailsObtained(detailsJson["ensName"].getStr, detailsJson["address"].getStr, detailsJson["pubkey"].getStr) self.detailsObtained(detailsJson["ensName"].getStr, detailsJson["address"].getStr, detailsJson["pubkey"].getStr, detailsJson["isStatus"].getBool, detailsJson["expirationTime"].getInt)
method rowCount(self: EnsManager, index: QModelIndex = nil): int = method rowCount(self: EnsManager, index: QModelIndex = nil): int =
return self.usernames.len return self.usernames.len
@ -228,6 +252,22 @@ QtObject:
self.pendingUsernames.incl(ensUsername) self.pendingUsernames.incl(ensUsername)
self.add ensUsername self.add ensUsername
proc releaseEstimate(self: EnsManager, ensUsername: string, address: string): int {.slot.} =
var success: bool
result = releaseEstimateGas(ensUsername, address, success)
if not success:
result = 100000
proc release*(self: EnsManager, username: string, address: string, gas: string, gasPrice: string, password: string): string {.slot.} =
var success: bool
let response = release(username, address, gas, gasPrice, password, success)
result = $(%* { "result": %response, "success": %success })
if success:
self.transactionWasSent(response)
self.pendingUsernames.excl(username)
self.remove(username)
proc setPubKeyGasEstimate(self: EnsManager, ensUsername: string, address: string): int {.slot.} = proc setPubKeyGasEstimate(self: EnsManager, ensUsername: string, address: string): int {.slot.} =
var success: bool var success: bool
let pubKey = self.status.settings.getSetting[:string](Setting.PublicKey, "0x0") let pubKey = self.status.settings.getSetting[:string](Setting.PublicKey, "0x0")

View File

@ -16,6 +16,7 @@ import transactions
import algorithm import algorithm
import web3/[ethtypes, conversions], stew/byteutils, stint import web3/[ethtypes, conversions], stew/byteutils, stint
import libstatus/eth/contracts import libstatus/eth/contracts
import libstatus/eth/transactions as eth_transactions
import chronicles, libp2p/[multihash, multicodec, cid] import chronicles, libp2p/[multihash, multicodec, cid]
import ./settings as status_settings import ./settings as status_settings
@ -172,6 +173,54 @@ proc getPrice*(): Stuint[256] =
raise newException(RpcException, "Error getting ens username price: 0x") raise newException(RpcException, "Error getting ens username price: 0x")
result = fromHex(Stuint[256], response.result) result = fromHex(Stuint[256], response.result)
proc releaseEstimateGas*(username: string, address: string, success: var bool): int =
let
label = fromHex(FixedBytes[32], label(username))
ensUsernamesContract = contracts.getContract("ens-usernames")
release = Release(label: label)
var tx = transactions.buildTokenTransaction(parseAddress(address), ensUsernamesContract.address, "", "")
try:
let response = ensUsernamesContract.methods["release"].estimateGas(tx, release, success)
if success:
result = fromHex[int](response)
except RpcException as e:
raise
proc release*(username: string, address: string, gas, gasPrice, password: string, success: var bool): string =
let
label = fromHex(FixedBytes[32], label(username))
ensUsernamesContract = contracts.getContract("ens-usernames")
release = Release(label: label)
var tx = transactions.buildTokenTransaction(parseAddress(address), ensUsernamesContract.address, "", "")
try:
result = ensUsernamesContract.methods["release"].send(tx, release, password, success)
if success:
trackPendingTransaction(result, address, $ensUsernamesContract.address, PendingTransactionType.ReleaseENS, username)
except RpcException as e:
raise
proc getExpirationTime*(username: string, success: var bool): int =
let
label = fromHex(FixedBytes[32], label(username))
expTime = ExpirationTime(label: label)
ensUsernamesContract = contracts.getContract("ens-usernames")
var tx = transactions.buildTransaction(parseAddress("0x0000000000000000000000000000000000000000"), 0.u256)
tx.to = ensUsernamesContract.address.some
tx.data = ensUsernamesContract.methods["getExpirationTime"].encodeAbi(expTime)
var response = ""
try:
response = eth_transactions.call(tx).result
success = true
except RpcException as e:
success = false
error "Error obtaining expiration time", err=e.msg
if success:
result = fromHex[int](response)
proc extractCoordinates*(pubkey: string):tuple[x: string, y:string] = proc extractCoordinates*(pubkey: string):tuple[x: string, y:string] =
result = ("0x" & pubkey[4..67], "0x" & pubkey[68..131]) result = ("0x" & pubkey[4..67], "0x" & pubkey[68..131])

View File

@ -29,6 +29,12 @@ type
x*: FixedBytes[32] x*: FixedBytes[32]
y*: FixedBytes[32] y*: FixedBytes[32]
ExpirationTime* = object
label*: FixedBytes[32]
Release* = object
label*: FixedBytes[32]
ApproveAndCall*[N: static[int]] = object ApproveAndCall*[N: static[int]] = object
to*: Address to*: Address
value*: Stuint[256] value*: Stuint[256]

View File

@ -10,7 +10,7 @@ import
export export
GetPackData, PackData, BuyToken, ApproveAndCall, Transfer, BalanceOf, Register, SetPubkey, GetPackData, PackData, BuyToken, ApproveAndCall, Transfer, BalanceOf, Register, SetPubkey,
TokenOfOwnerByIndex, TokenPackId, TokenUri, FixedBytes, DynamicBytes, toHex, fromHex, TokenOfOwnerByIndex, TokenPackId, TokenUri, FixedBytes, DynamicBytes, toHex, fromHex,
decodeContractResponse, encodeAbi, estimateGas, send, call decodeContractResponse, encodeAbi, estimateGas, send, call, ExpirationTime, Release
logScope: logScope:
@ -204,7 +204,9 @@ proc allContracts(): seq[Contract] =
Contract(name: "ens-usernames", network: Network.Mainnet, address: parseAddress("0xDB5ac1a559b02E12F29fC0eC0e37Be8E046DEF49"), Contract(name: "ens-usernames", network: Network.Mainnet, address: parseAddress("0xDB5ac1a559b02E12F29fC0eC0e37Be8E046DEF49"),
methods: [ methods: [
("register", Method(signature: "register(bytes32,address,bytes32,bytes32)")), ("register", Method(signature: "register(bytes32,address,bytes32,bytes32)")),
("getPrice", Method(signature: "getPrice()")) ("getPrice", Method(signature: "getPrice()")),
("getExpirationTime", Method(signature: "getExpirationTime(bytes32)")),
("release", Method(signature: "release(bytes32)"))
].toTable ].toTable
), ),
Contract(name: "ens-resolver", network: Network.Mainnet, address: parseAddress("0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41"), Contract(name: "ens-resolver", network: Network.Mainnet, address: parseAddress("0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41"),
@ -234,10 +236,12 @@ proc allContracts(): seq[Contract] =
), ),
newErc721Contract("sticker-pack", Network.Testnet, parseAddress("0xf852198d0385c4b871e0b91804ecd47c6ba97351"), "PACK", false, @[("tokenPackId", Method(signature: "tokenPackId(uint256)"))]), newErc721Contract("sticker-pack", Network.Testnet, parseAddress("0xf852198d0385c4b871e0b91804ecd47c6ba97351"), "PACK", false, @[("tokenPackId", Method(signature: "tokenPackId(uint256)"))]),
newErc721Contract("kudos", Network.Testnet, parseAddress("0xcd520707fc68d153283d518b29ada466f9091ea8"), "KDO", true), newErc721Contract("kudos", Network.Testnet, parseAddress("0xcd520707fc68d153283d518b29ada466f9091ea8"), "KDO", true),
Contract(name: "ens-usernames", network: Network.Testnet, address: parseAddress("0x11d9F481effd20D76cEE832559bd9Aca25405841"), Contract(name: "ens-usernames", network: Network.Testnet, address: parseAddress("0xdaae165beb8c06e0b7613168138ebba774aff071"),
methods: [ methods: [
("register", Method(signature: "register(bytes32,address,bytes32,bytes32)")), ("register", Method(signature: "register(bytes32,address,bytes32,bytes32)")),
("getPrice", Method(signature: "getPrice()")) ("getPrice", Method(signature: "getPrice()")),
("getExpirationTime", Method(signature: "getExpirationTime(bytes32)")),
("release", Method(signature: "release(bytes32)"))
].toTable ].toTable
), ),
Contract(name: "ens-resolver", network: Network.Testnet, address: parseAddress("0x42D63ae25990889E35F215bC95884039Ba354115"), Contract(name: "ens-resolver", network: Network.Testnet, address: parseAddress("0x42D63ae25990889E35F215bC95884039Ba354115"),

View File

@ -24,7 +24,7 @@ proc sendTransaction*(tx: EthSend, password: string): RpcResponse =
trace "Transaction sent succesfully", hash=result.result trace "Transaction sent succesfully", hash=result.result
proc call*(tx: EthSend): RpcResponse = proc call*(tx: EthSend): RpcResponse =
let responseStr = core.callPrivateRPC("eth_call", %*[%tx]) let responseStr = core.callPrivateRPC("eth_call", %*[%tx, "latest"])
result = Json.decode(responseStr, RpcResponse) result = Json.decode(responseStr, RpcResponse)
if not result.error.isNil: if not result.error.isNil:
raise newException(RpcException, "Error calling method: " & result.error.message) raise newException(RpcException, "Error calling method: " & result.error.message)

View File

@ -10,8 +10,10 @@ Item {
property string username: "" property string username: ""
property string walletAddress: "-" property string walletAddress: "-"
property string key: "-" property string key: "-"
property var expiration: 0
signal backBtnClicked(); signal backBtnClicked();
signal usernameReleased(username: string);
StyledText { StyledText {
id: sectionTitle id: sectionTitle
@ -49,12 +51,17 @@ Item {
keyLbl.textToCopy = pubkey; keyLbl.textToCopy = pubkey;
walletAddressLbl.visible = true; walletAddressLbl.visible = true;
keyLbl.visible = true; keyLbl.visible = true;
releaseBtn.visible = isStatus
releaseBtn.enabled = (Date.now() / 1000) > expirationTime && expirationTime > 0 && profileModel.ens.preferredUsername != username
expiration = new Date(expirationTime * 1000).getTime()
} }
onLoading: { onLoading: {
loadingImg.active = isLoading loadingImg.active = isLoading
if(!isLoading) return; if(!isLoading) return;
walletAddressLbl.visible = false; walletAddressLbl.visible = false;
keyLbl.visible = false; keyLbl.visible = false;
releaseBtn.visible = false;
expiration = 0;
} }
} }
@ -84,6 +91,63 @@ Item {
anchors.topMargin: 24 anchors.topMargin: 24
} }
Component {
id: transactionDialogComponent
StatusETHTransactionModal {
onOpened: {
walletModel.gasView.getGasPricePredictions()
}
title: qsTr("Connect username with your pubkey")
onClosed: {
destroy()
}
estimateGasFunction: function(selectedAccount) {
if (username === "" || !selectedAccount) return 100000;
return profileModel.ens.releaseEstimate(Utils.removeStatusEns(username), selectedAccount.address)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
return profileModel.ens.release(username,
selectedAddress,
gasLimit,
gasPrice,
password)
}
onSuccess: function(){
usernameReleased(username);
}
width: 475
height: 500
}
}
StatusButton {
id: releaseBtn
visible: false
enabled: false
anchors.top: keyLbl.bottom
anchors.topMargin: 24
anchors.left: parent.left
anchors.leftMargin: 24
text: qsTrId("Release username")
onClicked: {
openPopup(transactionDialogComponent)
}
}
Text {
visible: releaseBtn.visible && !releaseBtn.enabled
anchors.top: releaseBtn.bottom
anchors.topMargin: 2
anchors.left: parent.left
anchors.leftMargin: 24
text: profileModel.ens.preferredUsername != username ?
qsTr("Username locked. You wont be able to release it until %1").arg(Utils.formatShortDateStr(new Date(expiration).toDateString())):
qsTr("This is current preferred username. It can't be released")
color: Style.current.darkGrey
}
StatusButton { StatusButton {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.padding anchors.bottomMargin: Style.current.padding

View File

@ -0,0 +1,95 @@
import QtQuick 2.14
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.14
import "../../../../../imports"
import "../../../../../shared"
import "../../../../../shared/status"
Item {
property string ensUsername: ""
signal okBtnClicked()
StyledText {
id: sectionTitle
//% "ENS usernames"
text: qsTrId("ens-usernames")
anchors.left: parent.left
anchors.leftMargin: Style.current.bigPadding
anchors.top: parent.top
anchors.topMargin: Style.current.bigPadding
font.weight: Font.Bold
font.pixelSize: 20
}
Rectangle {
id: circle
anchors.top: sectionTitle.bottom
anchors.topMargin: Style.current.bigPadding
anchors.horizontalCenter: parent.horizontalCenter
width: 60
height: 60
radius: 120
color: Style.current.blue
StyledText {
text: "✓"
opacity: 0.7
font.weight: Font.Bold
font.pixelSize: 18
color: Style.current.white
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
id: title
text: qsTr("Username removed")
anchors.top: circle.bottom
anchors.topMargin: Style.current.bigPadding
font.weight: Font.Bold
font.pixelSize: 24
anchors.left: parent.left
anchors.right: parent.right
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
StyledText {
id: subtitle
text: qsTr("The username %1 will be removed and your deposit will be returned once the transaction is mined").arg(ensUsername)
anchors.top: title.bottom
anchors.topMargin: 24
font.pixelSize: 14
anchors.left: parent.left
anchors.right: parent.right
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
StyledText {
id: progress
//% "You can follow the progress in the Transaction History section of your wallet."
text: qsTrId("ens-username-you-can-follow-progress")
anchors.top: subtitle.bottom
anchors.topMargin: 24
font.pixelSize: 12
anchors.left: parent.left
anchors.right: parent.right
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
color: Style.current.secondaryText
}
StatusButton {
id: startBtn
anchors.top: progress.bottom
anchors.topMargin: Style.current.padding
anchors.horizontalCenter: parent.horizontalCenter
//% "Ok, got it"
text: qsTrId("ens-got-it")
onClicked: okBtnClicked()
}
}

View File

@ -47,25 +47,33 @@ Item {
Qt.callLater(validateENS, ensUsername, isStatus) Qt.callLater(validateENS, ensUsername, isStatus)
} }
Loader { Component {
id: transactionDialog id: transactionDialogComponent
function open() { StatusETHTransactionModal {
this.active = true
this.item.open()
}
function closed() {
this.active = false // kill an opened instance
}
sourceComponent: SetPubKeyModal {
onOpened: { onOpened: {
walletModel.gasView.getGasPricePredictions() walletModel.gasView.getGasPricePredictions()
} }
title: qsTr("Connect username with your pubkey")
onClosed: { onClosed: {
transactionDialog.closed() destroy()
} }
ensUsername: ensUsername.text || "" estimateGasFunction: function(selectedAccount) {
width: 400 if (ensUsername.text === "" || !selectedAccount) return 80000;
height: 400 return profileModel.ens.setPubKeyGasEstimate(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ), selectedAccount.address)
}
onSendTransaction: function(selectedAddress, gasLimit, gasPrice, password) {
return profileModel.ens.setPubKey(ensUsername.text + (isStatus ? ".stateofus.eth" : "" ),
selectedAddress,
gasLimit,
gasPrice,
password)
}
onSuccess: function(){
usernameUpdated(ensUsername.text);
}
width: 475
height: 500
} }
} }
@ -181,7 +189,7 @@ Item {
} }
if(ensStatus === Constants.ens_connected_dkey || ensStatus === Constants.ens_owned){ if(ensStatus === Constants.ens_connected_dkey || ensStatus === Constants.ens_owned){
transactionDialog.open(); openPopup(transactionDialogComponent)
return; return;
} }
} }

View File

@ -140,6 +140,10 @@ Item {
targetState: welcomeState targetState: welcomeState
signal: goToWelcome signal: goToWelcome
} }
DSM.SignalTransition {
targetState: ensReleasedState
signal: done
}
} }
DSM.State { DSM.State {
@ -176,6 +180,15 @@ Item {
} }
} }
DSM.State {
id: ensReleasedState
onEntered:loader.sourceComponent = ensReleased
DSM.SignalTransition {
targetState: listState
signal: next
}
}
DSM.State { DSM.State {
id: ensConnectedState id: ensConnectedState
onEntered:loader.sourceComponent = ensConnected onEntered:loader.sourceComponent = ensConnected
@ -240,6 +253,14 @@ Item {
} }
} }
Component {
id: ensReleased
ENSReleased {
ensUsername: selectedUsername
onOkBtnClicked: next(null)
}
}
Component { Component {
id: ensConnected id: ensConnected
ENSConnected { ENSConnected {
@ -265,6 +286,10 @@ Item {
ENSDetails { ENSDetails {
username: selectedUsername username: selectedUsername
onBackBtnClicked: back(); onBackBtnClicked: back();
onUsernameReleased: {
selectedUsername = username;
done(username);
}
} }
} }

View File

@ -2,17 +2,52 @@ import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.13
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.3
import "../../../../../imports" import "../../imports"
import "../../../../../shared" import "../../shared"
import "../../../../../shared/status" import "../../shared/status"
ModalPopup { ModalPopup {
id: root id: root
readonly property var asset: {"name": "Ethereum", "symbol": "ETH"} readonly property var asset: {"name": "Ethereum", "symbol": "ETH"}
property string ensUsername: ""
//% "Connect username with your pubkey" title: qsTr("Contract interaction")
title: qsTrId("connect-username-with-your-pubkey")
property var estimateGasFunction: (function(userAddress) { return 0; })
property var onSendTransaction: (function(userAddress, gasLimit, gasPrice, password){ return ""; })
property var onSuccess: (function(){})
Component.onCompleted: {
walletModel.gasView.getGasPricePredictions()
}
function sendTransaction() {
try {
let responseStr = onSendTransaction(selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
transactionSigner.enteredPassword);
let response = JSON.parse(responseStr)
if (!response.success) {
if (Utils.isInvalidPasswordMessage(response.result)){
//% "Wrong password"
transactionSigner.validationError = qsTrId("wrong-password")
return
}
sendingError.text = response.result
return sendingError.open()
}
onSuccess();
root.close();
} catch (e) {
console.error('Error sending the transaction', e)
sendingError.text = "Error sending the transaction: " + e.message;
return sendingError.open()
}
}
property MessageDialog sendingError: MessageDialog { property MessageDialog sendingError: MessageDialog {
id: sendingError id: sendingError
@ -22,33 +57,6 @@ ModalPopup {
standardButtons: StandardButton.Ok standardButtons: StandardButton.Ok
} }
function sendTransaction() {
try {
let responseStr = profileModel.ens.setPubKey(root.ensUsername,
selectFromAccount.selectedAccount.address,
gasSelector.selectedGasLimit,
gasSelector.selectedGasPrice,
transactionSigner.enteredPassword)
let response = JSON.parse(responseStr)
if (!response.success) {
if (Utils.isInvalidPasswordMessage(response.error.message)){
//% "Wrong password"
transactionSigner.validationError = qsTrId("wrong-password")
return
}
sendingError.text = response.error.message
return sendingError.open()
}
usernameUpdated(root.ensUsername);
} catch (e) {
console.error('Error sending the transaction', e)
sendingError.text = "Error sending the transaction: " + e.message;
return sendingError.open()
}
}
TransactionStackView { TransactionStackView {
id: stack id: stack
height: parent.height height: parent.height
@ -61,8 +69,7 @@ ModalPopup {
} }
TransactionFormGroup { TransactionFormGroup {
id: group1 id: group1
//% "Connect username with your pubkey" headerText: root.title
headerText: qsTrId("connect-username-with-your-pubkey")
//% "Continue" //% "Continue"
footerText: qsTrId("continue") footerText: qsTrId("continue")
@ -104,11 +111,9 @@ ModalPopup {
getFiatValue: walletModel.balanceView.getFiatValue getFiatValue: walletModel.balanceView.getFiatValue
defaultCurrency: walletModel.balanceView.defaultCurrency defaultCurrency: walletModel.balanceView.defaultCurrency
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() { property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
if (!(root.ensUsername !== "" && selectFromAccount.selectedAccount)) { let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount);
selectedGasLimit = 80000; gasSelector.selectedGasLimit = estimatedGas
return; return estimatedGas;
}
selectedGasLimit = profileModel.ens.setPubKeyGasEstimate(root.ensUsername, selectFromAccount.selectedAccount.address)
}) })
} }
GasValidator { GasValidator {
@ -123,8 +128,7 @@ ModalPopup {
} }
TransactionFormGroup { TransactionFormGroup {
id: group3 id: group3
//% "Connect username with your pubkey" headerText: root.title
headerText: qsTrId("connect-username-with-your-pubkey")
//% "Sign with password" //% "Sign with password"
footerText: qsTrId("sign-with-password") footerText: qsTrId("sign-with-password")
@ -148,8 +152,7 @@ ModalPopup {
} }
TransactionFormGroup { TransactionFormGroup {
id: group4 id: group4
//% "Connect username with your pubkey" headerText: root.title
headerText: qsTrId("connect-username-with-your-pubkey")
//% "Sign with password" //% "Sign with password"
footerText: qsTrId("sign-with-password") footerText: qsTrId("sign-with-password")
@ -164,6 +167,23 @@ ModalPopup {
footer: Item { footer: Item {
width: parent.width width: parent.width
height: btnNext.height height: btnNext.height
StatusRoundButton {
id: btnBack
anchors.left: parent.left
icon.name: "arrow-right"
icon.width: 20
icon.height: 16
rotation: 180
visible: stack.currentGroup.showBackBtn
enabled: stack.currentGroup.isValid || stack.isLastGroup
onClicked: {
if (typeof stack.currentGroup.onBackClicked === "function") {
return stack.currentGroup.onBackClicked()
}
stack.back()
}
}
StatusButton { StatusButton {
id: btnNext id: btnNext

View File

@ -115,7 +115,9 @@ ModalPopup {
defaultCurrency: walletModel.balanceView.defaultCurrency defaultCurrency: walletModel.balanceView.defaultCurrency
width: stack.width width: stack.width
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() { property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
return root.estimateGasFunction(selectFromAccount.selectedAccount, uuid); let estimatedGas = root.estimateGasFunction(selectFromAccount.selectedAccount, uuid);
gasSelector.selectedGasLimit = estimatedGas
return estimatedGas;
}) })
} }
GasValidator { GasValidator {