fix: rebase gone wrong
This commit is contained in:
parent
2f1416e042
commit
f2a56c70e1
|
@ -5,7 +5,7 @@ import ../../status/messages as messages_model
|
||||||
import ../../status/signals/types
|
import ../../status/signals/types
|
||||||
import ../../status/libstatus/types as status_types
|
import ../../status/libstatus/types as status_types
|
||||||
import ../../status/libstatus/settings as status_settings
|
import ../../status/libstatus/settings as status_settings
|
||||||
import ../../status/[chat, contacts, status, wallet]
|
import ../../status/[chat, contacts, status, wallet, stickers]
|
||||||
import view, views/channels_list, views/message_list
|
import view, views/channels_list, views/message_list
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
|
|
|
@ -75,9 +75,13 @@ proc handleChatEvents(self: ChatController) =
|
||||||
self.status.events.on("chat:connected") do(e: Args):
|
self.status.events.on("chat:connected") do(e: Args):
|
||||||
self.view.setConnected(true)
|
self.view.setConnected(true)
|
||||||
|
|
||||||
self.status.events.on(PendingTransactionType.BuyingStickerPack.event) do(e: Args):
|
self.status.events.on(PendingTransactionType.BuyStickerPack.confirmed) do(e: Args):
|
||||||
var data = TransactionMinedArgs(e).data
|
var tx = TransactionMinedArgs(e)
|
||||||
self.view.installStickerPack(data.parseInt)
|
if tx.success:
|
||||||
|
self.view.installStickerPack(tx.data.parseInt)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
# TODO: self.view.toastMessage(message = tx.revertReason, error = true) # for when the toast messages in the design are implemented
|
||||||
|
|
||||||
proc handleMailserverEvents(self: ChatController) =
|
proc handleMailserverEvents(self: ChatController) =
|
||||||
self.status.events.on("mailserverTopics") do(e: Args):
|
self.status.events.on("mailserverTopics") do(e: Args):
|
||||||
|
|
|
@ -118,7 +118,6 @@ QtObject:
|
||||||
result = $(%* { "result": %response })
|
result = $(%* { "result": %response })
|
||||||
# TODO:
|
# TODO:
|
||||||
# check if response["error"] is not null and handle the error
|
# check if response["error"] is not null and handle the error
|
||||||
self.status.wallet.trackPendingTransaction(address, response, PendingTransactionType.BuyingStickerPack, $packId)
|
|
||||||
except RpcException as e:
|
except RpcException as e:
|
||||||
result = $(%* { "error": %* { "message": %e.msg }})
|
result = $(%* { "error": %* { "message": %e.msg }})
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ../../status/[status, contacts]
|
||||||
import ../../status/chat as status_chat
|
import ../../status/chat as status_chat
|
||||||
import ../../status/devices
|
import ../../status/devices
|
||||||
import ../../status/chat/chat
|
import ../../status/chat/chat
|
||||||
|
import ../../status/wallet
|
||||||
import view
|
import view
|
||||||
import views/ens_manager
|
import views/ens_manager
|
||||||
import chronicles
|
import chronicles
|
||||||
|
@ -78,3 +79,19 @@ proc init*(self: ProfileController, account: Account) =
|
||||||
self.view.updateContactList(msgData.contacts)
|
self.view.updateContactList(msgData.contacts)
|
||||||
if msgData.installations.len > 0:
|
if msgData.installations.len > 0:
|
||||||
self.view.addDevices(msgData.installations)
|
self.view.addDevices(msgData.installations)
|
||||||
|
|
||||||
|
self.status.events.on(PendingTransactionType.RegisterENS.confirmed) do(e: Args):
|
||||||
|
let tx = TransactionMinedArgs(e)
|
||||||
|
if tx.success:
|
||||||
|
self.view.ens.confirm(TransactionMinedArgs(e).data)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
# TODO: show toast message indicating transaction reverted
|
||||||
|
|
||||||
|
self.status.events.on(PendingTransactionType.SetPubKey.confirmed) do(e: Args):
|
||||||
|
let tx = TransactionMinedArgs(e)
|
||||||
|
if tx.success:
|
||||||
|
self.view.ens.confirm(TransactionMinedArgs(e).data)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
# TODO: show toast message indicating transaction reverted
|
|
@ -4,7 +4,7 @@ import json
|
||||||
import json_serialization
|
import json_serialization
|
||||||
import sequtils
|
import sequtils
|
||||||
import strutils
|
import strutils
|
||||||
from ../../../status/libstatus/types import Setting
|
from ../../../status/libstatus/types import Setting, PendingTransactionType
|
||||||
import ../../../status/threads
|
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
|
||||||
|
@ -13,14 +13,20 @@ 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
|
from eth/common/utils import parseAddress
|
||||||
|
import ../../../status/wallet
|
||||||
|
import sets
|
||||||
|
import stew/byteutils
|
||||||
|
import eth/common/eth_types, stew/byteutils
|
||||||
|
|
||||||
type
|
type
|
||||||
EnsRoles {.pure.} = enum
|
EnsRoles {.pure.} = enum
|
||||||
UserName = UserRole + 1
|
UserName = UserRole + 1
|
||||||
|
IsPending = UserRole + 2
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type EnsManager* = ref object of QAbstractListModel
|
type EnsManager* = ref object of QAbstractListModel
|
||||||
usernames*: seq[string]
|
usernames*: seq[string]
|
||||||
|
pendingUsernames*: HashSet[string]
|
||||||
status: Status
|
status: Status
|
||||||
|
|
||||||
proc setup(self: EnsManager) = self.QAbstractListModel.setup
|
proc setup(self: EnsManager) = self.QAbstractListModel.setup
|
||||||
|
@ -33,11 +39,20 @@ QtObject:
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result.usernames = @[]
|
result.usernames = @[]
|
||||||
result.status = status
|
result.status = status
|
||||||
|
result.pendingUsernames = initHashSet[string]()
|
||||||
result.setup
|
result.setup
|
||||||
|
|
||||||
proc init*(self: EnsManager) =
|
proc init*(self: EnsManager) =
|
||||||
self.usernames = status_settings.getSetting[seq[string]](Setting.Usernames, @[])
|
self.usernames = status_settings.getSetting[seq[string]](Setting.Usernames, @[])
|
||||||
|
|
||||||
|
# Get pending ens names
|
||||||
|
let pendingTransactions = status_wallet.getPendingTransactions().parseJson["result"]
|
||||||
|
for trx in pendingTransactions.getElems():
|
||||||
|
if trx["type"].getStr == $PendingTransactionType.RegisterENS:
|
||||||
|
self.usernames.add trx["data"].getStr
|
||||||
|
self.pendingUsernames.incl trx["data"].getStr
|
||||||
|
|
||||||
|
|
||||||
proc ensWasResolved*(self: EnsManager, ensResult: string) {.signal.}
|
proc ensWasResolved*(self: EnsManager, ensResult: string) {.signal.}
|
||||||
|
|
||||||
proc ensResolved(self: EnsManager, ensResult: string) {.slot.} =
|
proc ensResolved(self: EnsManager, ensResult: string) {.slot.} =
|
||||||
|
@ -80,7 +95,14 @@ QtObject:
|
||||||
|
|
||||||
proc preferredUsernameChanged(self: EnsManager) {.signal.}
|
proc preferredUsernameChanged(self: EnsManager) {.signal.}
|
||||||
|
|
||||||
|
proc isPending*(self: EnsManager, ensUsername: string): bool {.slot.} =
|
||||||
|
self.pendingUsernames.contains(ensUsername)
|
||||||
|
|
||||||
|
proc pendingLen*(self: EnsManager): int {.slot.} =
|
||||||
|
self.pendingUsernames.len
|
||||||
|
|
||||||
proc setPreferredUsername(self: EnsManager, newENS: string) {.slot.} =
|
proc setPreferredUsername(self: EnsManager, newENS: string) {.slot.} =
|
||||||
|
if not self.isPending(newENS):
|
||||||
discard status_settings.saveSetting(Setting.PreferredUsername, newENS)
|
discard status_settings.saveSetting(Setting.PreferredUsername, newENS)
|
||||||
self.preferredUsernameChanged()
|
self.preferredUsernameChanged()
|
||||||
|
|
||||||
|
@ -89,16 +111,10 @@ QtObject:
|
||||||
notify = preferredUsernameChanged
|
notify = preferredUsernameChanged
|
||||||
write = setPreferredUsername
|
write = setPreferredUsername
|
||||||
|
|
||||||
proc connect(self: EnsManager, username: string, isStatus: bool) {.slot.} =
|
proc connect(self: EnsManager, ensUsername: string) =
|
||||||
var ensUsername = username
|
|
||||||
if isStatus:
|
|
||||||
ensUsername = ensUsername & status_ens.domain
|
|
||||||
var usernames = status_settings.getSetting[seq[string]](Setting.Usernames, @[])
|
var usernames = status_settings.getSetting[seq[string]](Setting.Usernames, @[])
|
||||||
usernames.add ensUsername
|
usernames.add ensUsername
|
||||||
discard status_settings.saveSetting(Setting.Usernames, %*usernames)
|
discard status_settings.saveSetting(Setting.Usernames, %*usernames)
|
||||||
if usernames.len == 1:
|
|
||||||
self.setPreferredUsername(ensUsername)
|
|
||||||
self.add ensUsername
|
|
||||||
|
|
||||||
proc loading(self: EnsManager, isLoading: bool) {.signal.}
|
proc loading(self: EnsManager, isLoading: bool) {.signal.}
|
||||||
|
|
||||||
|
@ -129,13 +145,27 @@ QtObject:
|
||||||
if index.row < 0 or index.row >= self.usernames.len:
|
if index.row < 0 or index.row >= self.usernames.len:
|
||||||
return
|
return
|
||||||
let username = self.usernames[index.row]
|
let username = self.usernames[index.row]
|
||||||
result = newQVariant(username)
|
case role.EnsRoles:
|
||||||
|
of EnsRoles.UserName: result = newQVariant(username)
|
||||||
|
of EnsRoles.IsPending: result = newQVariant(self.pendingUsernames.contains(username))
|
||||||
|
|
||||||
method roleNames(self: EnsManager): Table[int, string] =
|
method roleNames(self: EnsManager): Table[int, string] =
|
||||||
{
|
{
|
||||||
EnsRoles.UserName.int:"username"
|
EnsRoles.UserName.int:"username",
|
||||||
|
EnsRoles.IsPending.int: "isPending"
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
|
proc usernameConfirmed(self: EnsManager, username: string) {.signal.}
|
||||||
|
|
||||||
|
proc confirm*(self: EnsManager, ensUsername: string) =
|
||||||
|
self.connect(ensUsername)
|
||||||
|
self.pendingUsernames.excl ensUsername
|
||||||
|
let msgIdx = self.usernames.find(ensUsername)
|
||||||
|
let topLeft = self.createIndex(msgIdx, 0, nil)
|
||||||
|
let bottomRight = self.createIndex(msgIdx, 0, nil)
|
||||||
|
self.dataChanged(topLeft, bottomRight, @[EnsRoles.IsPending.int])
|
||||||
|
self.usernameConfirmed(ensUsername)
|
||||||
|
|
||||||
proc getPrice(self: EnsManager): string {.slot.} =
|
proc getPrice(self: EnsManager): string {.slot.} =
|
||||||
result = libstatus_utils.wei2Eth(getPrice())
|
result = libstatus_utils.wei2Eth(getPrice())
|
||||||
|
|
||||||
|
@ -145,15 +175,37 @@ QtObject:
|
||||||
proc getENSRegistry(self: EnsManager): string {.slot.} =
|
proc getENSRegistry(self: EnsManager): string {.slot.} =
|
||||||
result = registry
|
result = registry
|
||||||
|
|
||||||
|
proc formatUsername(username: string, isStatus: bool): string =
|
||||||
|
result = username
|
||||||
|
if isStatus:
|
||||||
|
result = result & status_ens.domain
|
||||||
|
|
||||||
|
proc connectOwnedUsername(self: EnsManager, username: string, isStatus: bool) {.slot.} =
|
||||||
|
var ensUsername = formatUsername(username, isStatus)
|
||||||
|
|
||||||
|
self.usernames.add ensUsername
|
||||||
|
self.add ensUsername
|
||||||
|
|
||||||
|
self.connect(ensUsername)
|
||||||
|
|
||||||
proc registerENS(self: EnsManager, username: string, password: string) {.slot.} =
|
proc registerENS(self: EnsManager, username: string, password: string) {.slot.} =
|
||||||
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||||
let address = parseAddress(status_wallet.getWalletAccounts()[0].address)
|
let address = status_wallet.getWalletAccounts()[0].address
|
||||||
discard registerUsername(username, address, pubKey, password)
|
let walletAddress = parseAddress(address)
|
||||||
self.connect(username, true)
|
let trxHash = registerUsername(username, walletAddress, pubKey, password)
|
||||||
|
|
||||||
|
# TODO: handle transaction failure
|
||||||
|
var ensUsername = formatUsername(username, true)
|
||||||
|
self.pendingUsernames.incl(ensUsername)
|
||||||
|
self.add ensUsername
|
||||||
|
|
||||||
proc setPubKey(self: EnsManager, username: string, password: string) {.slot.} =
|
proc setPubKey(self: EnsManager, username: string, password: string) {.slot.} =
|
||||||
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||||
let address = parseAddress(status_wallet.getWalletAccounts()[0].address)
|
let address = status_wallet.getWalletAccounts()[0].address
|
||||||
discard setPubKey(username, address, pubKey, password)
|
let walletAddress = parseAddress(address)
|
||||||
self.connect(username, username.endsWith(domain))
|
let trxHash = setPubKey(username, walletAddress, pubKey, password)
|
||||||
|
|
||||||
|
# TODO: handle transaction failure
|
||||||
|
self.pendingUsernames.incl(username)
|
||||||
|
self.add username
|
||||||
|
|
|
@ -25,7 +25,6 @@ proc delete*(self: WalletController) =
|
||||||
delete self.view
|
delete self.view
|
||||||
|
|
||||||
proc init*(self: WalletController) =
|
proc init*(self: WalletController) =
|
||||||
status_wallet.startWallet()
|
|
||||||
self.status.wallet.initAccounts()
|
self.status.wallet.initAccounts()
|
||||||
var accounts = self.status.wallet.accounts
|
var accounts = self.status.wallet.accounts
|
||||||
for account in accounts:
|
for account in accounts:
|
||||||
|
@ -60,3 +59,9 @@ proc init*(self: WalletController) =
|
||||||
|
|
||||||
# TODO: handle these data.eventType: history, reorg
|
# TODO: handle these data.eventType: history, reorg
|
||||||
# see status-react/src/status_im/ethereum/subscriptions.cljs
|
# see status-react/src/status_im/ethereum/subscriptions.cljs
|
||||||
|
|
||||||
|
proc checkPendingTransactions*(self: WalletController) =
|
||||||
|
self.status.wallet.checkPendingTransactions() # TODO: consider doing this in a spawnAndSend
|
||||||
|
|
||||||
|
proc start*(self: WalletController) =
|
||||||
|
status_wallet.startWallet()
|
|
@ -85,6 +85,9 @@ proc mainProc() =
|
||||||
wallet.init()
|
wallet.init()
|
||||||
chat.init()
|
chat.init()
|
||||||
|
|
||||||
|
wallet.checkPendingTransactions()
|
||||||
|
wallet.start()
|
||||||
|
|
||||||
engine.setRootContextProperty("loginModel", login.variant)
|
engine.setRootContextProperty("loginModel", login.variant)
|
||||||
engine.setRootContextProperty("onboardingModel", onboarding.variant)
|
engine.setRootContextProperty("onboardingModel", onboarding.variant)
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,11 @@ import strformat
|
||||||
import libstatus/core
|
import libstatus/core
|
||||||
import libstatus/types
|
import libstatus/types
|
||||||
import libstatus/utils
|
import libstatus/utils
|
||||||
|
import libstatus/wallet
|
||||||
import stew/byteutils
|
import stew/byteutils
|
||||||
import unicode
|
import unicode
|
||||||
import algorithm
|
import algorithm
|
||||||
import eth/common/eth_types, stew/byteutils
|
import eth/common/eth_types, stew/byteutils, stint
|
||||||
import libstatus/eth/contracts
|
import libstatus/eth/contracts
|
||||||
const domain* = ".stateofus.eth"
|
const domain* = ".stateofus.eth"
|
||||||
|
|
||||||
|
@ -168,6 +169,8 @@ proc registerUsername*(username:string, address: EthAddress, pubKey: string, pas
|
||||||
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)
|
||||||
|
|
||||||
|
trackPendingTransaction(response.result, $address, $sntContract.address, PendingTransactionType.RegisterENS, username & domain)
|
||||||
|
|
||||||
result = response.result
|
result = response.result
|
||||||
|
|
||||||
proc setPubKey*(username:string, address: EthAddress, pubKey: string, password: string): string =
|
proc setPubKey*(username:string, address: EthAddress, pubKey: string, password: string): string =
|
||||||
|
@ -184,9 +187,11 @@ proc setPubKey*(username:string, address: EthAddress, pubKey: string, password:
|
||||||
setPubkey = SetPubkey(label: label, x: x, y: y)
|
setPubkey = SetPubkey(label: label, x: x, y: y)
|
||||||
setPubkeyAbiEncoded = resolverContract.methods["setPubkey"].encodeAbi(setPubkey)
|
setPubkeyAbiEncoded = resolverContract.methods["setPubkey"].encodeAbi(setPubkey)
|
||||||
|
|
||||||
|
let resolverAddress = resolver(hash)
|
||||||
|
|
||||||
let payload = %* {
|
let payload = %* {
|
||||||
"from": $address,
|
"from": $address,
|
||||||
"to": resolver(hash),
|
"to": resolverAddress,
|
||||||
# "gas": 200000, # TODO: obtain gas price?
|
# "gas": 200000, # TODO: obtain gas price?
|
||||||
"data": setPubkeyAbiEncoded
|
"data": setPubkeyAbiEncoded
|
||||||
}
|
}
|
||||||
|
@ -195,6 +200,9 @@ proc setPubKey*(username:string, address: EthAddress, pubKey: string, 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 setting the pubkey: " & response.error.message)
|
raise newException(RpcException, "Error setting the pubkey: " & response.error.message)
|
||||||
|
|
||||||
|
trackPendingTransaction(response.result, $address, resolverAddress, PendingTransactionType.SetPubKey, username)
|
||||||
|
|
||||||
result = response.result
|
result = response.result
|
||||||
|
|
||||||
proc statusRegistrarAddress*():string =
|
proc statusRegistrarAddress*():string =
|
||||||
|
|
|
@ -17,7 +17,7 @@ proc callPrivateRPC*(methodName: string, payload = %* []): string =
|
||||||
"method": methodName,
|
"method": methodName,
|
||||||
"params": %payload
|
"params": %payload
|
||||||
}
|
}
|
||||||
debug "calling json", request = $inputJSON
|
debug "callPrivateRPC", rpc_method=methodName
|
||||||
let response = nim_status.callPrivateRPC($inputJSON)
|
let response = nim_status.callPrivateRPC($inputJSON)
|
||||||
result = $response
|
result = $response
|
||||||
if parseJSON(result).hasKey("error"):
|
if parseJSON(result).hasKey("error"):
|
||||||
|
|
|
@ -98,7 +98,7 @@ proc allContracts(): seq[Contract] = @[
|
||||||
("getPrice", Method(signature: "getPrice()"))
|
("getPrice", Method(signature: "getPrice()"))
|
||||||
].toTable
|
].toTable
|
||||||
),
|
),
|
||||||
Contract(name: "ens-usernames", network: Network.Testnet, address: parseAddress("0x76fbf2815ead80006d07a64c1fd5dc9964ab3c93"),
|
Contract(name: "ens-usernames", network: Network.Testnet, address: parseAddress("0x11d9F481effd20D76cEE832559bd9Aca25405841"),
|
||||||
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()"))
|
||||||
|
|
|
@ -236,3 +236,10 @@ proc `%`*(x: EthSend): JsonNode =
|
||||||
result["data"] = %x.data
|
result["data"] = %x.data
|
||||||
if x.nonce.isSome:
|
if x.nonce.isSome:
|
||||||
result["nonce"] = %x.nonce.unsafeGet
|
result["nonce"] = %x.nonce.unsafeGet
|
||||||
|
|
||||||
|
type PendingTransactionType* {.pure.} = enum
|
||||||
|
RegisterENS = "RegisterENS",
|
||||||
|
SetPubKey = "SetPubKey",
|
||||||
|
ReleaseENS = "ReleaseENS",
|
||||||
|
BuyStickerPack = "BuyStickerPack"
|
||||||
|
WalletTransfer = "WalletTransfer"
|
||||||
|
|
|
@ -93,3 +93,19 @@ proc hex2Token*(input: string, decimals: int): string =
|
||||||
result = $i
|
result = $i
|
||||||
if(r > 0): result = fmt"{result}.{d}"
|
if(r > 0): result = fmt"{result}.{d}"
|
||||||
|
|
||||||
|
proc trackPendingTransaction*(transactionHash: string, fromAddress: string, toAddress: string, trxType: PendingTransactionType, data: string) =
|
||||||
|
let blockNumber = parseInt($fromHex(Stuint[256], getBlockByNumber("latest").parseJson()["result"]["number"].getStr))
|
||||||
|
let payload = %* [{"transactionHash": transactionHash, "blockNumber": blockNumber, "from_address": fromAddress, "to_address": toAddress, "type": $trxType, "data": data}]
|
||||||
|
discard callPrivateRPC("wallet_storePendingTransaction", payload)
|
||||||
|
|
||||||
|
proc getPendingTransactions*(): string =
|
||||||
|
let payload = %* []
|
||||||
|
result = callPrivateRPC("wallet_getPendingTransactions", payload)
|
||||||
|
|
||||||
|
proc getPendingOutboundTransactionsByAddress*(address: string): string =
|
||||||
|
let payload = %* [address]
|
||||||
|
result = callPrivateRPC("wallet_getPendingOutboundTransactionsByAddress", payload)
|
||||||
|
|
||||||
|
proc deletePendingTransaction*(transactionHash: string) =
|
||||||
|
let payload = %* [transactionHash]
|
||||||
|
discard callPrivateRPC("wallet_deletePendingTransaction", payload)
|
||||||
|
|
|
@ -4,19 +4,9 @@ import libstatus/accounts as libstatus_accounts
|
||||||
import libstatus/core as libstatus_core
|
import libstatus/core as libstatus_core
|
||||||
import libstatus/settings as libstatus_settings
|
import libstatus/settings as libstatus_settings
|
||||||
import libstatus/types as libstatus_types
|
import libstatus/types as libstatus_types
|
||||||
|
import chat, accounts, wallet, node, network, mailservers, messages, contacts, profile, stickers
|
||||||
|
|
||||||
import chat as chat
|
export chat, accounts, node, mailservers, messages, contacts, profile, network
|
||||||
import accounts as accounts
|
|
||||||
import wallet as wallet
|
|
||||||
import node as node
|
|
||||||
import mailservers as mailservers
|
|
||||||
import messages as messages
|
|
||||||
import contacts as contacts
|
|
||||||
import profile
|
|
||||||
import network as network
|
|
||||||
import stickers
|
|
||||||
|
|
||||||
export stickers
|
|
||||||
|
|
||||||
type Status* = ref object
|
type Status* = ref object
|
||||||
events*: EventEmitter
|
events*: EventEmitter
|
||||||
|
|
|
@ -7,9 +7,11 @@ from eth/common/utils import parseAddress
|
||||||
|
|
||||||
import # local deps
|
import # local deps
|
||||||
libstatus/types, libstatus/eth/contracts as status_contracts,
|
libstatus/types, libstatus/eth/contracts as status_contracts,
|
||||||
libstatus/stickers as status_stickers, transactions
|
libstatus/stickers as status_stickers, transactions,
|
||||||
|
libstatus/wallet
|
||||||
from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, toUInt64
|
from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, toUInt64
|
||||||
|
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "stickers-model"
|
topics = "stickers-model"
|
||||||
|
|
||||||
|
@ -82,6 +84,7 @@ proc buyPack*(self: StickersModel, packId: int, address, price, gas, gasPrice, p
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
result = sntContract.methods["approveAndCall"].send(tx, approveAndCall, password)
|
result = sntContract.methods["approveAndCall"].send(tx, approveAndCall, password)
|
||||||
|
trackPendingTransaction(result, address, $sntContract.address, PendingTransactionType.BuyStickerPack, $packId)
|
||||||
except RpcException as e:
|
except RpcException as e:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ import libstatus/settings as status_settings
|
||||||
import libstatus/wallet as status_wallet
|
import libstatus/wallet as status_wallet
|
||||||
import libstatus/accounts/constants as constants
|
import libstatus/accounts/constants as constants
|
||||||
import libstatus/eth/[eth, contracts]
|
import libstatus/eth/[eth, contracts]
|
||||||
from libstatus/types import GeneratedAccount, DerivedAccount, Transaction, Setting, GasPricePrediction, EthSend, Quantity, `%`, StatusGoException, Network, RpcResponse, RpcException, `$`
|
from libstatus/core import getBlockByNumber
|
||||||
|
from libstatus/types import PendingTransactionType, GeneratedAccount, DerivedAccount, Transaction, Setting, GasPricePrediction, EthSend, Quantity, `%`, StatusGoException, Network, RpcResponse, RpcException
|
||||||
from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, first, toUInt64
|
from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, first, toUInt64
|
||||||
import wallet/[balance_manager, account, collectibles]
|
import wallet/[balance_manager, account, collectibles]
|
||||||
import transactions
|
import transactions
|
||||||
|
@ -19,23 +20,13 @@ export Transaction
|
||||||
logScope:
|
logScope:
|
||||||
topics = "wallet-model"
|
topics = "wallet-model"
|
||||||
|
|
||||||
type PendingTransactionType* {.pure.} = enum
|
proc confirmed*(self:PendingTransactionType):string =
|
||||||
RegisterENS = "RegisterENS",
|
|
||||||
ReleaseENS = "ReleaseENS",
|
|
||||||
BuyingStickerPack = "BuyingStickerPack"
|
|
||||||
|
|
||||||
proc event*(self:PendingTransactionType):string =
|
|
||||||
result = "transaction:" & $self
|
result = "transaction:" & $self
|
||||||
|
|
||||||
type PendingTransaction* = object
|
|
||||||
transactionHash*: string
|
|
||||||
blockNumber*: int
|
|
||||||
trxType*: PendingTransactionType
|
|
||||||
data*: string
|
|
||||||
mined: bool
|
|
||||||
|
|
||||||
type TransactionMinedArgs* = ref object of Args
|
type TransactionMinedArgs* = ref object of Args
|
||||||
data*: string
|
data*: string
|
||||||
|
success*: bool
|
||||||
|
revertReason*: string # TODO: possible to get revert reason in here?
|
||||||
|
|
||||||
type WalletModel* = ref object
|
type WalletModel* = ref object
|
||||||
events*: EventEmitter
|
events*: EventEmitter
|
||||||
|
@ -43,7 +34,6 @@ type WalletModel* = ref object
|
||||||
defaultCurrency*: string
|
defaultCurrency*: string
|
||||||
tokens*: JsonNode
|
tokens*: JsonNode
|
||||||
totalBalance*: float
|
totalBalance*: float
|
||||||
pendingTransactions: Table[string, seq[PendingTransaction]]
|
|
||||||
|
|
||||||
proc getDefaultCurrency*(self: WalletModel): string
|
proc getDefaultCurrency*(self: WalletModel): string
|
||||||
proc calculateTotalFiatBalance*(self: WalletModel)
|
proc calculateTotalFiatBalance*(self: WalletModel)
|
||||||
|
@ -52,7 +42,6 @@ proc newWalletModel*(events: EventEmitter): WalletModel =
|
||||||
result = WalletModel()
|
result = WalletModel()
|
||||||
result.accounts = @[]
|
result.accounts = @[]
|
||||||
result.tokens = %* []
|
result.tokens = %* []
|
||||||
result.pendingTransactions = initTable[string, seq[PendingTransaction]]()
|
|
||||||
result.events = events
|
result.events = events
|
||||||
result.defaultCurrency = ""
|
result.defaultCurrency = ""
|
||||||
result.totalBalance = 0.0
|
result.totalBalance = 0.0
|
||||||
|
@ -89,35 +78,27 @@ proc estimateGas*(self: WalletModel, source, to, value: string): int =
|
||||||
except RpcException as e:
|
except RpcException as e:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
proc trackPendingTransaction*(self: WalletModel, address: string, trxHash: string, trxType: PendingTransactionType, data: string) =
|
|
||||||
let latestBlock = getBlockByNumber("latest").parseJson()["result"].getInt
|
|
||||||
|
|
||||||
if not self.pendingTransactions.hasKey(address):
|
|
||||||
self.pendingTransactions[address] = @[]
|
|
||||||
|
|
||||||
self.pendingTransactions[address].add PendingTransaction(
|
|
||||||
transactionHash: trxHash,
|
|
||||||
trxType: trxType,
|
|
||||||
blockNumber: latestBlock,
|
|
||||||
data: data,
|
|
||||||
mined: false
|
|
||||||
)
|
|
||||||
|
|
||||||
proc getTransactionReceipt*(self: WalletModel, transactionHash: string): JsonNode =
|
proc getTransactionReceipt*(self: WalletModel, transactionHash: string): JsonNode =
|
||||||
result = status_wallet.getTransactionReceipt(transactionHash).parseJSON()["result"]
|
result = status_wallet.getTransactionReceipt(transactionHash).parseJSON()["result"]
|
||||||
|
|
||||||
proc checkPendingTransactions*(self: WalletModel, address: string, blockNumber: int) =
|
proc confirmTransactionStatus(self: WalletModel, pendingTransactions: JsonNode, blockNumber: int) =
|
||||||
if not self.pendingTransactions.hasKey(address): return
|
for trx in pendingTransactions.getElems():
|
||||||
for trx in self.pendingTransactions[address].mitems:
|
let transactionReceipt = self.getTransactionReceipt(trx["transactionHash"].getStr)
|
||||||
if trx.mined: continue
|
|
||||||
|
|
||||||
let transactionReceipt = self.getTransactionReceipt(trx.transactionHash)
|
|
||||||
if transactionReceipt.kind != JNull:
|
if transactionReceipt.kind != JNull:
|
||||||
trx.mined = true
|
status_wallet.deletePendingTransaction(trx["transactionHash"].getStr)
|
||||||
if transactionReceipt{"status"}.getStr == "0x1": # mined successfully
|
let ev = TransactionMinedArgs(
|
||||||
self.events.emit(trx.trxType.event, TransactionMinedArgs(data: trx.data))
|
data: trx["data"].getStr,
|
||||||
else:
|
success: transactionReceipt{"status"}.getStr == "0x1",
|
||||||
discard # TODO: what should we do if the transaction reverted?
|
revertReason: ""
|
||||||
|
)
|
||||||
|
self.events.emit(parseEnum[PendingTransactionType](trx["type"].getStr).confirmed, ev)
|
||||||
|
|
||||||
|
proc checkPendingTransactions*(self: WalletModel) =
|
||||||
|
let latestBlock = parseInt($fromHex(Stuint[256], getBlockByNumber("latest").parseJson()["result"]["number"].getStr))
|
||||||
|
self.confirmTransactionStatus(status_wallet.getPendingTransactions().parseJson["result"], latestBlock)
|
||||||
|
|
||||||
|
proc checkPendingTransactions*(self: WalletModel, address: string, blockNumber: int) =
|
||||||
|
self.confirmTransactionStatus(status_wallet.getPendingOutboundTransactionsByAddress(address).parseJson["result"], blockNumber)
|
||||||
|
|
||||||
proc estimateTokenGas*(self: WalletModel, source, to, assetAddress, value: string): int =
|
proc estimateTokenGas*(self: WalletModel, source, to, assetAddress, value: string): int =
|
||||||
var
|
var
|
||||||
|
|
|
@ -21,8 +21,11 @@ ModalPopup {
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: lbl1
|
id: lbl1
|
||||||
|
text: profileModel.ens.preferredUsername ?
|
||||||
//% "Your messages are displayed to others with this username:"
|
//% "Your messages are displayed to others with this username:"
|
||||||
text: qsTrId("your-messages-are-displayed-to-others-with-this-username-")
|
qsTrId("your-messages-are-displayed-to-others-with-this-username-")
|
||||||
|
:
|
||||||
|
qsTr("Once you select a username, you won’t be able to disable it afterwards. You will only be able choose a different username to display.")
|
||||||
font.pixelSize: 15
|
font.pixelSize: 15
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,16 @@ Item {
|
||||||
property string identicon: profileModel.profile.identicon
|
property string identicon: profileModel.profile.identicon
|
||||||
property int timestamp: 1577872140
|
property int timestamp: 1577872140
|
||||||
|
|
||||||
|
function shouldDisplayExampleMessage(){
|
||||||
|
return profileModel.ens.rowCount() > 0 && profileModel.ens.pendingLen() != profileModel.ens.rowCount() && profileModel.ens.preferredUsername !== ""
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: statusENS
|
id: statusENS
|
||||||
Item {
|
Item {
|
||||||
Text {
|
Text {
|
||||||
id: usernameTxt
|
id: usernameTxt
|
||||||
text: username.substr(0, username.indexOf("."))
|
text: username.substr(0, username.indexOf(".")) + " " + (isPending ? qsTr("(pending)") : "")
|
||||||
color: Style.current.textColor
|
color: Style.current.textColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +50,7 @@ Item {
|
||||||
Item {
|
Item {
|
||||||
Text {
|
Text {
|
||||||
id: usernameTxt
|
id: usernameTxt
|
||||||
text: username
|
text: username + " " + (isPending ? qsTr("(pending)") : "")
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
color: Style.current.textColor
|
color: Style.current.textColor
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
@ -90,6 +94,7 @@ Item {
|
||||||
Loader {
|
Loader {
|
||||||
sourceComponent: model.username.endsWith(".stateofus.eth") ? statusENS : normalENS
|
sourceComponent: model.username.endsWith(".stateofus.eth") ? statusENS : normalENS
|
||||||
property string username: model.username
|
property string username: model.username
|
||||||
|
property bool isPending: model.isPending
|
||||||
active: true
|
active: true
|
||||||
anchors.left: circle.right
|
anchors.left: circle.right
|
||||||
anchors.leftMargin: Style.current.smallPadding
|
anchors.leftMargin: Style.current.smallPadding
|
||||||
|
@ -192,7 +197,7 @@ Item {
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: chatSettingsLabel
|
id: chatSettingsLabel
|
||||||
visible: profileModel.ens.rowCount() > 1
|
visible: profileModel.ens.rowCount() > 0 && profileModel.ens.pendingLen() != profileModel.ens.rowCount()
|
||||||
//% "Chat Settings"
|
//% "Chat Settings"
|
||||||
text: qsTrId("chat-settings")
|
text: qsTrId("chat-settings")
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -222,7 +227,7 @@ Item {
|
||||||
StyledText {
|
StyledText {
|
||||||
id: usernameLabel2
|
id: usernameLabel2
|
||||||
visible: chatSettingsLabel.visible
|
visible: chatSettingsLabel.visible
|
||||||
text: profileModel.ens.preferredUsername
|
text: profileModel.ens.preferredUsername || qsTr("None selected")
|
||||||
anchors.left: usernameLabel.right
|
anchors.left: usernameLabel.right
|
||||||
anchors.leftMargin: Style.current.padding
|
anchors.leftMargin: Style.current.padding
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
|
@ -236,7 +241,9 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.top: profileModel.ens.rowCount() == 1 ? separator.bottom : preferredUsername.bottom
|
id: messagesShownAs
|
||||||
|
visible: shouldDisplayExampleMessage()
|
||||||
|
anchors.top: !visible ? separator.bottom : preferredUsername.bottom
|
||||||
anchors.topMargin: Style.current.padding * 2
|
anchors.topMargin: Style.current.padding * 2
|
||||||
|
|
||||||
UserImage {
|
UserImage {
|
||||||
|
@ -290,7 +297,28 @@ Item {
|
||||||
anchors.right: chatBox.right
|
anchors.right: chatBox.right
|
||||||
anchors.rightMargin: Style.current.padding
|
anchors.rightMargin: Style.current.padding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.top: chatTime.bottom
|
||||||
|
anchors.left: chatImage.left
|
||||||
|
anchors.topMargin: Style.current.padding
|
||||||
|
text: qsTr("You’re displaying your ENS username in chats")
|
||||||
|
font.pixelSize: 14
|
||||||
|
color: Style.current.secondaryText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: profileModel.ens
|
||||||
|
onPreferredUsernameChanged: {
|
||||||
|
messagesShownAs.visible = shouldDisplayExampleMessage()
|
||||||
|
}
|
||||||
|
onUsernameConfirmed: {
|
||||||
|
messagesShownAs.visible = shouldDisplayExampleMessage()
|
||||||
|
chatSettingsLabel.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -202,7 +202,7 @@ Item {
|
||||||
if(!valid) return;
|
if(!valid) return;
|
||||||
|
|
||||||
if(ensStatus === "connected"){
|
if(ensStatus === "connected"){
|
||||||
profileModel.ens.connect(ensUsername.text, isStatus);
|
profileModel.ens.connectOwnedUsername(ensUsername.text, isStatus);
|
||||||
continueClicked(ensStatus, ensUsername.text)
|
continueClicked(ensStatus, ensUsername.text)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,7 @@ Item {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.bottomMargin: Style.current.padding
|
anchors.bottomMargin: Style.current.padding
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
disabled: profileModel.network !== "mainnet_rpc"
|
disabled: profileModel.network !== "mainnet_rpc" // Comment this to use on testnet
|
||||||
//% "Start"
|
//% "Start"
|
||||||
label: !disabled ? qsTrId("start") : qsTr("Only available on Mainnet")
|
label: !disabled ? qsTrId("start") : qsTr("Only available on Mainnet")
|
||||||
onClicked: startBtnClicked()
|
onClicked: startBtnClicked()
|
||||||
|
|
|
@ -25,8 +25,8 @@ Item {
|
||||||
signal goToWelcome();
|
signal goToWelcome();
|
||||||
signal goToList();
|
signal goToList();
|
||||||
|
|
||||||
function goToStart(){
|
function goToStart(){ /* Comment this to use on testnet */
|
||||||
if(profileModel.ens.rowCount() > 0){
|
if(profileModel.ens.rowCount() > 0 && profileModel.network === "mainnet_rpc"){
|
||||||
goToList();
|
goToList();
|
||||||
} else {
|
} else {
|
||||||
goToWelcome();
|
goToWelcome();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8f83c5f462de854fa9b616273ccfdd4b0bda4748
|
Subproject commit abf9c789c3b688611a053e1ddb49d28d21d6d162
|
Loading…
Reference in New Issue