feat: register status ens usernames
This commit is contained in:
parent
1d0e4fe2cf
commit
8f1f01b6a0
|
@ -8,9 +8,10 @@ import ../../../status/threads
|
||||||
import ../../../status/ens as status_ens
|
import ../../../status/ens as status_ens
|
||||||
import ../../../status/libstatus/wallet as status_wallet
|
import ../../../status/libstatus/wallet as status_wallet
|
||||||
import ../../../status/libstatus/settings as status_settings
|
import ../../../status/libstatus/settings as status_settings
|
||||||
import ../../../status/libstatus/utils as utils
|
import ../../../status/libstatus/utils as libstatus_utils
|
||||||
import ../../../status/libstatus/tokens as tokens
|
import ../../../status/libstatus/tokens as tokens
|
||||||
import ../../../status/status
|
import ../../../status/status
|
||||||
|
from eth/common/utils import parseAddress
|
||||||
|
|
||||||
type
|
type
|
||||||
EnsRoles {.pure.} = enum
|
EnsRoles {.pure.} = enum
|
||||||
|
@ -135,10 +136,17 @@ QtObject:
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
proc getPrice(self: EnsManager): string {.slot.} =
|
proc getPrice(self: EnsManager): string {.slot.} =
|
||||||
result = utils.wei2Eth(getPrice())
|
result = libstatus_utils.wei2Eth(getPrice())
|
||||||
|
|
||||||
proc getUsernameRegistrar(self: EnsManager): string {.slot.} =
|
proc getUsernameRegistrar(self: EnsManager): string {.slot.} =
|
||||||
result = statusRegistrarAddress()
|
result = statusRegistrarAddress()
|
||||||
|
|
||||||
proc getENSRegistry(self: EnsManager): string {.slot.} =
|
proc getENSRegistry(self: EnsManager): string {.slot.} =
|
||||||
result = registry
|
result = registry
|
||||||
|
|
||||||
|
proc registerENS(self: EnsManager, username: string, password: string) {.slot.} =
|
||||||
|
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||||
|
let address = parseAddress(status_wallet.getWalletAccounts()[0].address)
|
||||||
|
discard registerUsername(username & status_ens.domain, address, pubKey, password)
|
||||||
|
self.connect(username, true)
|
||||||
|
|
|
@ -133,19 +133,23 @@ 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 registerUsername*(username:string, address: EthAddress, pubKey: string, price: Stuint[256], password: string): string =
|
proc extractCoordinates*(pubkey: string):tuple[x: string, y:string] =
|
||||||
let label = fromHex(FixedBytes[32], namehash(addDomain(username)))
|
result = ("0x" & pubkey[4..67], "0x" & pubkey[68..131])
|
||||||
let x = fromHex(FixedBytes[32], "0x" & pubkey[4..67])
|
|
||||||
let y = fromHex(FixedBytes[32], "0x" & pubkey[68..131])
|
proc registerUsername*(username:string, address: EthAddress, pubKey: string, password: string): string =
|
||||||
let
|
let
|
||||||
|
label = fromHex(FixedBytes[32], namehash(addDomain(username)))
|
||||||
|
coordinates = extractCoordinates(pubkey)
|
||||||
|
x = fromHex(FixedBytes[32], coordinates.x)
|
||||||
|
y = fromHex(FixedBytes[32], coordinates.y)
|
||||||
ensUsernamesContract = contracts.getContract("ens-usernames")
|
ensUsernamesContract = contracts.getContract("ens-usernames")
|
||||||
sntContract = contracts.getContract("snt")
|
sntContract = contracts.getContract("snt")
|
||||||
price = getPrice()
|
price = getPrice()
|
||||||
register = Register(label: label, account: address, x: x, y: y)
|
|
||||||
registerAbiEncoded = ensUsernamesContract.methods["register"].encodeAbi(register)
|
|
||||||
|
|
||||||
let
|
let
|
||||||
approveAndCallObj = ApproveAndCall(to: ensUsernamesContract.address, value: price, data: DynamicBytes[136].fromHex(registerAbiEncoded))
|
register = Register(label: label, account: address, x: x, y: y)
|
||||||
|
registerAbiEncoded = ensUsernamesContract.methods["register"].encodeAbi(register)
|
||||||
|
approveAndCallObj = ApproveAndCall(to: ensUsernamesContract.address, value: price, data: DynamicBytes[132].fromHex(registerAbiEncoded))
|
||||||
approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(approveAndCallObj)
|
approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(approveAndCallObj)
|
||||||
|
|
||||||
let payload = %* {
|
let payload = %* {
|
||||||
|
@ -154,12 +158,11 @@ proc registerUsername*(username:string, address: EthAddress, pubKey: string, pri
|
||||||
# "gas": 200000, # TODO: obtain gas price?
|
# "gas": 200000, # TODO: obtain gas price?
|
||||||
"data": approveAndCallAbiEncoded
|
"data": approveAndCallAbiEncoded
|
||||||
}
|
}
|
||||||
|
|
||||||
let responseStr = sendTransaction($payload, password)
|
let responseStr = sendTransaction($payload, password)
|
||||||
let response = Json.decode(responseStr, RpcResponse)
|
let response = Json.decode(responseStr, RpcResponse)
|
||||||
if not response.error.isNil:
|
if not response.error.isNil:
|
||||||
raise newException(RpcException, "Error registering ens-username: " & response.error.message)
|
raise newException(RpcException, "Error registering ens-username: " & response.error.message)
|
||||||
result = response.result # should be a tx receipt
|
result = response.result
|
||||||
|
|
||||||
proc statusRegistrarAddress*():string =
|
proc statusRegistrarAddress*():string =
|
||||||
result = $contracts.getContract("ens-usernames").address
|
result = $contracts.getContract("ens-usernames").address
|
||||||
|
|
|
@ -36,7 +36,7 @@ type
|
||||||
ApproveAndCall* = object
|
ApproveAndCall* = object
|
||||||
to*: EthAddress
|
to*: EthAddress
|
||||||
value*: Stuint[256]
|
value*: Stuint[256]
|
||||||
data*: DynamicBytes[136]
|
data*: DynamicBytes[132]
|
||||||
|
|
||||||
Transfer* = object
|
Transfer* = object
|
||||||
to*: EthAddress
|
to*: EthAddress
|
||||||
|
|
|
@ -134,7 +134,7 @@ proc buyPack*(packId: Stuint[256], address: EthAddress, price: Stuint[256], pass
|
||||||
buyToken = BuyToken(packId: packId, address: address, price: price)
|
buyToken = BuyToken(packId: packId, address: address, price: price)
|
||||||
buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(buyToken)
|
buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(buyToken)
|
||||||
let
|
let
|
||||||
approveAndCallObj = ApproveAndCall(to: stickerMktContract.address, value: price, data: DynamicBytes[136].fromHex(buyTxAbiEncoded))
|
approveAndCallObj = ApproveAndCall(to: stickerMktContract.address, value: price, data: DynamicBytes[132].fromHex(buyTxAbiEncoded))
|
||||||
approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(approveAndCallObj)
|
approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(approveAndCallObj)
|
||||||
let payload = %* {
|
let payload = %* {
|
||||||
"from": $address,
|
"from": $address,
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import "../../../../../imports"
|
||||||
|
import "../../../../../shared"
|
||||||
|
|
||||||
|
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 added")
|
||||||
|
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("Nice! You own %1.stateofus.eth once the transaction is complete.").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
|
||||||
|
text: qsTr("You can follow the progress in the Transaction History section of your wallet.")
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledButton {
|
||||||
|
id: startBtn
|
||||||
|
anchors.top: progress.bottom
|
||||||
|
anchors.topMargin: Style.current.padding
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
label: qsTr("Ok, got it")
|
||||||
|
onClicked: okBtnClicked()
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,10 @@ import "../../../../../imports"
|
||||||
import "../../../../../shared"
|
import "../../../../../shared"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property var onClick: function(){}
|
|
||||||
|
|
||||||
property string username: ""
|
property string username: ""
|
||||||
|
|
||||||
signal backBtnClicked();
|
signal backBtnClicked();
|
||||||
|
signal usernameRegistered(userName: string);
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: sectionTitle
|
id: sectionTitle
|
||||||
|
@ -23,6 +22,35 @@ Item {
|
||||||
font.pixelSize: 20
|
font.pixelSize: 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModalPopup {
|
||||||
|
id: transactionDialog
|
||||||
|
title: qsTr("TODO: replace this for the transaction dialog")
|
||||||
|
|
||||||
|
Input {
|
||||||
|
id: passwd
|
||||||
|
placeholderText: "Password"
|
||||||
|
anchors.top: parent.textToCopy
|
||||||
|
anchors.topMargin: 24
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 24
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledButton {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: Style.current.padding
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Style.current.padding
|
||||||
|
label: qsTr("Ok")
|
||||||
|
onClicked: {
|
||||||
|
profileModel.ens.registerENS(username, passwd.text)
|
||||||
|
passwd.text = "";
|
||||||
|
usernameRegistered(username);
|
||||||
|
transactionDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ModalPopup {
|
ModalPopup {
|
||||||
id: popup
|
id: popup
|
||||||
title: qsTr("Terms of name registration")
|
title: qsTr("Terms of name registration")
|
||||||
|
@ -292,8 +320,8 @@ Item {
|
||||||
anchors.bottomMargin: Style.current.padding
|
anchors.bottomMargin: Style.current.padding
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Style.current.padding
|
anchors.rightMargin: Style.current.padding
|
||||||
label: parseFloat(walletModel.getSNTBalance()) < 10 ? qsTr("Not enough SNT") : qsTr("Ok")
|
label: parseFloat(walletModel.getSNTBalance()) < 10 ? qsTr("Not enough SNT") : qsTr("Register")
|
||||||
disabled: parseFloat(walletModel.getSNTBalance()) < 10 || !termsAndConditionsCheckbox.checked
|
disabled: parseFloat(walletModel.getSNTBalance()) < 10 || !termsAndConditionsCheckbox.checked
|
||||||
onClicked: onClick()
|
onClicked: transactionDialog.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ Item {
|
||||||
|
|
||||||
signal next(output: string)
|
signal next(output: string)
|
||||||
signal back()
|
signal back()
|
||||||
|
signal done(ensUsername: string)
|
||||||
signal connect(ensUsername: string)
|
signal connect(ensUsername: string)
|
||||||
|
|
||||||
signal goToWelcome();
|
signal goToWelcome();
|
||||||
|
@ -149,6 +150,23 @@ Item {
|
||||||
targetState: listState
|
targetState: listState
|
||||||
signal: back
|
signal: back
|
||||||
}
|
}
|
||||||
|
DSM.SignalTransition {
|
||||||
|
targetState: listState
|
||||||
|
signal: back
|
||||||
|
}
|
||||||
|
DSM.SignalTransition {
|
||||||
|
targetState: ensRegisteredState
|
||||||
|
signal: done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DSM.State {
|
||||||
|
id: ensRegisteredState
|
||||||
|
onEntered:loader.sourceComponent = ensRegistered
|
||||||
|
DSM.SignalTransition {
|
||||||
|
targetState: listState
|
||||||
|
signal: next
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,10 +200,8 @@ Item {
|
||||||
id: termsAndConditions
|
id: termsAndConditions
|
||||||
TermsAndConditions {
|
TermsAndConditions {
|
||||||
username: selectedUsername
|
username: selectedUsername
|
||||||
onClick: function(output){
|
|
||||||
next(output);
|
|
||||||
}
|
|
||||||
onBackBtnClicked: back();
|
onBackBtnClicked: back();
|
||||||
|
onUsernameRegistered: done(userName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +212,14 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: ensRegistered
|
||||||
|
ENSRegistered {
|
||||||
|
ensUsername: selectedUsername
|
||||||
|
onOkBtnClicked: next(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: list
|
id: list
|
||||||
List {
|
List {
|
||||||
|
|
Loading…
Reference in New Issue