parent
0c1dc30e5a
commit
2d0c95feb3
|
@ -124,11 +124,12 @@ proc newAppController*(appService: AppService): AppController =
|
|||
# Services
|
||||
result.keychainService = keychain_service.newService(appService.status.events)
|
||||
result.settingService = setting_service.newService()
|
||||
result.settingsService = settings_service.newService()
|
||||
result.accountsService = accounts_service.newService()
|
||||
result.contactsService = contacts_service.newService(appService.status.events, appService.threadpool)
|
||||
result.chatService = chat_service.newService()
|
||||
result.communityService = community_service.newService(result.chatService)
|
||||
result.tokenService = token_service.newService(appService.status.events, result.settingService)
|
||||
result.tokenService = token_service.newService(appService.status.events, appService.threadpool, result.settingService, result.settingsService)
|
||||
result.collectibleService = collectible_service.newService(result.settingService)
|
||||
result.walletAccountService = wallet_account_service.newService(
|
||||
appService.status.events, result.settingService, result.tokenService
|
||||
|
@ -136,7 +137,6 @@ proc newAppController*(appService: AppService): AppController =
|
|||
result.transactionService = transaction_service.newService(appService.status.events, appService.threadpool, result.walletAccountService)
|
||||
result.bookmarkService = bookmark_service.newService()
|
||||
result.profileService = profile_service.newService()
|
||||
result.settingsService = settings_service.newService()
|
||||
result.aboutService = about_service.newService()
|
||||
result.dappPermissionsService = dapp_permissions_service.newService()
|
||||
result.languageService = language_service.newService()
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import ./controller_interface
|
||||
import ./io_interface
|
||||
import eventemitter
|
||||
import ../../../../../app_service/service/token/service as token_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
|
||||
|
@ -6,16 +8,19 @@ export controller_interface
|
|||
|
||||
type
|
||||
Controller*[T: controller_interface.DelegateInterface] = ref object of controller_interface.AccessInterface
|
||||
delegate: T
|
||||
tokenService: token_service.ServiceInterface
|
||||
delegate: io_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
tokenService: token_service.Service
|
||||
walletAccountService: wallet_account_service.ServiceInterface
|
||||
|
||||
proc newController*[T](
|
||||
delegate: T,
|
||||
tokenService: token_service.ServiceInterface,
|
||||
delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
tokenService: token_service.Service,
|
||||
walletAccountService: wallet_account_service.ServiceInterface,
|
||||
): Controller[T] =
|
||||
result = Controller[T]()
|
||||
result.events = events
|
||||
result.delegate = delegate
|
||||
result.tokenService = tokenService
|
||||
result.walletAccountService = walletAccountService
|
||||
|
@ -24,7 +29,9 @@ method delete*[T](self: Controller[T]) =
|
|||
discard
|
||||
|
||||
method init*[T](self: Controller[T]) =
|
||||
discard
|
||||
self.events.on(SIGNAL_TOKEN_DETAILS_LOADED) do(e:Args):
|
||||
let args = TokenDetailsLoadedArgs(e)
|
||||
self.delegate.tokenDetailsWereResolved(args.tokenDetails)
|
||||
|
||||
method getTokens*[T](self: Controller[T]): seq[token_service.TokenDto] =
|
||||
return self.tokenService.getTokens()
|
||||
|
@ -36,4 +43,7 @@ method toggleVisible*[T](self: Controller[T], symbol: string) =
|
|||
self.walletAccountService.toggleTokenVisible(symbol)
|
||||
|
||||
method removeCustomToken*[T](self: Controller[T], address: string) =
|
||||
self.tokenService.removeCustomToken(address)
|
||||
self.tokenService.removeCustomToken(address)
|
||||
|
||||
method getTokenDetails*[T](self: Controller[T], address: string) =
|
||||
self.tokenService.getTokenDetails(address)
|
|
@ -1,4 +1,4 @@
|
|||
import ../../../../../app_service/service/token/service_interface as token_service
|
||||
import ../../../../../app_service/service/token/service as token_service
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
@ -22,6 +22,9 @@ method toggleVisible*(self: AccessInterface, symbol: string) =
|
|||
method removeCustomToken*(self: AccessInterface, address: string) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getTokenDetails*(self: AccessInterface, address: string) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
type
|
||||
## Abstract class (concept) which must be implemented by object/s used in this
|
||||
## module.
|
||||
|
|
|
@ -23,6 +23,12 @@ method removeCustomToken*(self: AccessInterface, address: string) {.base.} =
|
|||
method refreshTokens*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getTokenDetails*(self: AccessInterface, address: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method tokenDetailsWereResolved*(self: AccessInterface, tokenDetails: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
type
|
||||
## Abstract class (concept) which must be implemented by object/s used in this
|
||||
## module.
|
||||
|
|
|
@ -20,14 +20,14 @@ type
|
|||
proc newModule*[T](
|
||||
delegate: T,
|
||||
events: EventEmitter,
|
||||
tokenService: token_service.ServiceInterface,
|
||||
tokenService: token_service.Service,
|
||||
walletAccountService: wallet_account_service.ServiceInterface,
|
||||
): Module[T] =
|
||||
result = Module[T]()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.view = newView(result)
|
||||
result.controller = controller.newController[Module[T]](result, tokenService, walletAccountService)
|
||||
result.controller = controller.newController[Module[T]](result, events, tokenService, walletAccountService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*[T](self: Module[T]) =
|
||||
|
@ -49,6 +49,7 @@ method refreshTokens*[T](self: Module[T]) =
|
|||
)
|
||||
|
||||
method load*[T](self: Module[T]) =
|
||||
self.controller.init()
|
||||
singletonInstance.engine.setRootContextProperty("walletSectionAllTokens", newQVariant(self.view))
|
||||
self.refreshTokens()
|
||||
|
||||
|
@ -73,4 +74,10 @@ method toggleVisible*[T](self: Module[T], symbol: string) =
|
|||
self.controller.toggleVisible(symbol)
|
||||
|
||||
method removeCustomToken*[T](self: Module[T], address: string) =
|
||||
self.controller.removeCustomToken(address)
|
||||
self.controller.removeCustomToken(address)
|
||||
|
||||
method getTokenDetails*[T](self: Module[T], address: string) =
|
||||
self.controller.getTokenDetails(address)
|
||||
|
||||
method tokenDetailsWereResolved*[T](self: Module[T], tokenDetails: string) =
|
||||
self.view.tokenDetailsWereResolved(tokenDetails)
|
|
@ -65,4 +65,9 @@ QtObject:
|
|||
self.delegate.toggleVisible(symbol)
|
||||
|
||||
proc removeCustomToken(self: View, address: string) {.slot.} =
|
||||
self.delegate.removeCustomToken(address)
|
||||
self.delegate.removeCustomToken(address)
|
||||
|
||||
proc tokenDetailsWereResolved*(self: View, tokenDetails: string) {.signal.}
|
||||
|
||||
proc getTokenDetails*(self: View, address: string) {.slot.} =
|
||||
self.delegate.getTokenDetails(address)
|
||||
|
|
|
@ -40,7 +40,7 @@ type
|
|||
proc newModule*[T](
|
||||
delegate: T,
|
||||
events: EventEmitter,
|
||||
tokenService: token_service.ServiceInterface,
|
||||
tokenService: token_service.Service,
|
||||
transactionService: transaction_service.Service,
|
||||
collectibleService: collectible_service.ServiceInterface,
|
||||
walletAccountService: wallet_account_service.ServiceInterface,
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# include strformat, json
|
||||
include ../../common/json_utils
|
||||
include ../../tasks/common
|
||||
import status/[utils, tokens]
|
||||
|
||||
#################################################
|
||||
# Async load transactions
|
||||
#################################################
|
||||
|
||||
type
|
||||
GetTokenDetailsTaskArg = ref object of QObjectTaskArg
|
||||
chainId: int
|
||||
address: string
|
||||
|
||||
|
||||
const getTokenDetailsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[GetTokenDetailsTaskArg](argEncoded)
|
||||
try:
|
||||
let
|
||||
tkn = newErc20Contract(arg.chainId, arg.address.parseAddress)
|
||||
decimals = tkn.tokenDecimals()
|
||||
output = %* {
|
||||
"address": arg.address,
|
||||
"name": tkn.tokenName(),
|
||||
"symbol": tkn.tokenSymbol(),
|
||||
"decimals": (if decimals == 0: "" else: $decimals)
|
||||
}
|
||||
arg.finish(output)
|
||||
except Exception as e:
|
||||
let output = %* {
|
||||
"address": arg.address,
|
||||
"error": fmt"{e.msg}. Is this an ERC-20 or ERC-721 contract?",
|
||||
}
|
||||
arg.finish(output)
|
|
@ -1,18 +1,30 @@
|
|||
import json, sequtils, chronicles
|
||||
import NimQml, json, sequtils, chronicles, strformat, strutils
|
||||
import eventemitter
|
||||
from sugar import `=>`
|
||||
import web3/ethtypes
|
||||
from web3/conversions import `$`
|
||||
import status/statusgo_backend_new/custom_tokens as custom_tokens
|
||||
import ../setting/service as setting_service
|
||||
import ../settings/service as settings_service
|
||||
|
||||
import ./service_interface, ./dto, ./static_token
|
||||
import ./dto, ./static_token
|
||||
|
||||
export service_interface
|
||||
export dto
|
||||
|
||||
logScope:
|
||||
topics = "token-service"
|
||||
|
||||
import ../../../app_service/[main]
|
||||
import ../../../app_service/tasks/[qt, threadpool]
|
||||
|
||||
include async_tasks
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TOKEN_DETAILS_LOADED* = "SIGNAL_TOKEN_DETAILS_LOADED"
|
||||
|
||||
type
|
||||
TokenDetailsLoadedArgs* = ref object of Args
|
||||
tokenDetails*: string
|
||||
|
||||
type
|
||||
CustomTokenAdded* = ref object of Args
|
||||
|
@ -26,96 +38,122 @@ type
|
|||
VisibilityToggled* = ref object of Args
|
||||
token*: TokenDto
|
||||
|
||||
type
|
||||
Service* = ref object of service_interface.ServiceInterface
|
||||
QtObject:
|
||||
type Service* = ref object of QObject
|
||||
events: EventEmitter
|
||||
threadpool: ThreadPool
|
||||
settingService: setting_service.Service
|
||||
settingsService: settings_service.Service
|
||||
tokens: seq[TokenDto]
|
||||
|
||||
method delete*(self: Service) =
|
||||
discard
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newService*(events: EventEmitter, settingService: setting_service.Service): Service =
|
||||
result = Service()
|
||||
result.events = events
|
||||
result.settingService = settingService
|
||||
result.tokens = @[]
|
||||
proc newService*(
|
||||
events: EventEmitter,
|
||||
threadpool: ThreadPool,
|
||||
settingService: setting_service.Service,
|
||||
settingsService: settings_service.Service
|
||||
): Service =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.events = events
|
||||
result.threadpool = threadpool
|
||||
result.settingService = settingService
|
||||
result.settingsService = settingsService
|
||||
result.tokens = @[]
|
||||
|
||||
method getDefaultVisibleSymbols(self: Service): seq[string] =
|
||||
let networkSlug = self.settingService.getSetting().currentNetwork.slug
|
||||
|
||||
if networkSlug == "mainnet_rpc":
|
||||
return @["SNT"]
|
||||
proc getDefaultVisibleSymbols(self: Service): seq[string] =
|
||||
let networkSlug = self.settingService.getSetting().currentNetwork.slug
|
||||
|
||||
if networkSlug == "mainnet_rpc":
|
||||
return @["SNT"]
|
||||
|
||||
if networkSlug == "testnet_rpc" or networkSlug == "rinkeby_rpc":
|
||||
return @["STT"]
|
||||
if networkSlug == "testnet_rpc" or networkSlug == "rinkeby_rpc":
|
||||
return @["STT"]
|
||||
|
||||
return @[]
|
||||
return @[]
|
||||
|
||||
|
||||
method init*(self: Service) =
|
||||
try:
|
||||
var activeTokenSymbols = self.settingService.getSetting().activeTokenSymbols
|
||||
if activeTokenSymbols.len == 0:
|
||||
activeTokenSymbols = self.getDefaultVisibleSymbols()
|
||||
proc init*(self: Service) =
|
||||
try:
|
||||
var activeTokenSymbols = self.settingService.getSetting().activeTokenSymbols
|
||||
if activeTokenSymbols.len == 0:
|
||||
activeTokenSymbols = self.getDefaultVisibleSymbols()
|
||||
|
||||
let static_tokens = static_token.all().map(
|
||||
proc(x: TokenDto): TokenDto =
|
||||
x.isVisible = activeTokenSymbols.contains(x.symbol)
|
||||
return x
|
||||
let static_tokens = static_token.all().map(
|
||||
proc(x: TokenDto): TokenDto =
|
||||
x.isVisible = activeTokenSymbols.contains(x.symbol)
|
||||
return x
|
||||
)
|
||||
|
||||
let response = custom_tokens.getCustomTokens()
|
||||
self.tokens = concat(
|
||||
static_tokens,
|
||||
map(response.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols))
|
||||
).filter(
|
||||
proc(x: TokenDto): bool = x.chainId == self.settingService.getSetting().currentNetwork.id
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
return
|
||||
|
||||
proc getTokens*(self: Service): seq[TokenDto] =
|
||||
return self.tokens
|
||||
|
||||
proc addCustomToken*(self: Service, address: string, name: string, symbol: string, decimals: int) =
|
||||
custom_tokens.addCustomToken(address, name, symbol, decimals, "")
|
||||
let token = newDto(
|
||||
name,
|
||||
self.settingService.getSetting().currentNetwork.id,
|
||||
fromHex(Address, address),
|
||||
symbol,
|
||||
decimals,
|
||||
false,
|
||||
true
|
||||
)
|
||||
self.tokens.add(token)
|
||||
self.events.emit("token/customTokenAdded", CustomTokenAdded(token: token))
|
||||
|
||||
let response = custom_tokens.getCustomTokens()
|
||||
self.tokens = concat(
|
||||
static_tokens,
|
||||
map(response.result.getElems(), proc(x: JsonNode): TokenDto = x.toTokenDto(activeTokenSymbols))
|
||||
).filter(
|
||||
proc(x: TokenDto): bool = x.chainId == self.settingService.getSetting().currentNetwork.id
|
||||
proc toggleVisible*(self: Service, symbol: string) =
|
||||
var tokenChanged = self.tokens[0]
|
||||
for token in self.tokens:
|
||||
if token.symbol == symbol:
|
||||
token.isVisible = not token.isVisible
|
||||
tokenChanged = token
|
||||
break
|
||||
|
||||
let visibleSymbols = self.tokens.filter(t => t.isVisible).map(t => t.symbol)
|
||||
discard self.settingService.saveSetting("wallet/visible-tokens", visibleSymbols)
|
||||
self.events.emit("token/visibilityToggled", VisibilityToggled(token: tokenChanged))
|
||||
|
||||
proc removeCustomToken*(self: Service, address: string) =
|
||||
custom_tokens.removeCustomToken(address)
|
||||
var index = -1
|
||||
|
||||
for idx, token in self.tokens.pairs():
|
||||
if $token.address == address:
|
||||
index = idx
|
||||
break
|
||||
|
||||
let tokenRemoved = self.tokens[index]
|
||||
self.tokens.del(index)
|
||||
self.events.emit("token/customTokenRemoved", CustomTokenRemoved(token: tokenRemoved))
|
||||
|
||||
proc tokenDetailsResolved*(self: Service, tokenDetails: string) {.slot.} =
|
||||
self.events.emit(SIGNAL_TOKEN_DETAILS_LOADED, TokenDetailsLoadedArgs(
|
||||
tokenDetails: tokenDetails
|
||||
))
|
||||
|
||||
proc getTokenDetails*(self: Service, address: string) =
|
||||
let chainId = self.settingsService.getCurrentNetworkDetails().config.networkId
|
||||
let arg = GetTokenDetailsTaskArg(
|
||||
tptr: cast[ByteAddress](getTokenDetailsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "tokenDetailsResolved",
|
||||
chainId: chainId,
|
||||
address: address
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
return
|
||||
|
||||
method getTokens*(self: Service): seq[TokenDto] =
|
||||
return self.tokens
|
||||
|
||||
method addCustomToken*(self: Service, address: string, name: string, symbol: string, decimals: int) =
|
||||
custom_tokens.addCustomToken(address, name, symbol, decimals, "")
|
||||
let token = newDto(
|
||||
name,
|
||||
self.settingService.getSetting().currentNetwork.id,
|
||||
fromHex(Address, address),
|
||||
symbol,
|
||||
decimals,
|
||||
false,
|
||||
true
|
||||
)
|
||||
self.tokens.add(token)
|
||||
self.events.emit("token/customTokenAdded", CustomTokenAdded(token: token))
|
||||
|
||||
method toggleVisible*(self: Service, symbol: string) =
|
||||
var tokenChanged = self.tokens[0]
|
||||
for token in self.tokens:
|
||||
if token.symbol == symbol:
|
||||
token.isVisible = not token.isVisible
|
||||
tokenChanged = token
|
||||
break
|
||||
|
||||
let visibleSymbols = self.tokens.filter(t => t.isVisible).map(t => t.symbol)
|
||||
discard self.settingService.saveSetting("wallet/visible-tokens", visibleSymbols)
|
||||
self.events.emit("token/visibilityToggled", VisibilityToggled(token: tokenChanged))
|
||||
|
||||
method removeCustomToken*(self: Service, address: string) =
|
||||
custom_tokens.removeCustomToken(address)
|
||||
var index = -1
|
||||
|
||||
for idx, token in self.tokens.pairs():
|
||||
if $token.address == address:
|
||||
index = idx
|
||||
break
|
||||
|
||||
let tokenRemoved = self.tokens[index]
|
||||
self.tokens.del(index)
|
||||
self.events.emit("token/customTokenRemoved", CustomTokenRemoved(token: tokenRemoved))
|
||||
self.threadpool.start(arg)
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import dto
|
||||
|
||||
export dto
|
||||
|
||||
type
|
||||
ServiceInterface* {.pure inheritable.} = ref object of RootObj
|
||||
## Abstract class for this service access.
|
||||
|
||||
method delete*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method init*(self: ServiceInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getTokens*(self: ServiceInterface): seq[TokenDto] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method addCustomToken*(self: ServiceInterface, address: string, name: string, symbol: string, decimals: int) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method toggleVisible*(self: ServiceInterface, symbol: string) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method removeCustomToken*(self: ServiceInterface, address: string) =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -57,7 +57,7 @@ ModalPopup {
|
|||
}
|
||||
|
||||
property var getTokenDetails: Backpressure.debounce(popup, 500, function (tokenAddress){
|
||||
RootStore.customTokenList.getTokenDetails(tokenAddress)
|
||||
RootStore.walletTokensModule.getTokenDetails(tokenAddress)
|
||||
});
|
||||
|
||||
function onKeyReleased(){
|
||||
|
@ -70,7 +70,7 @@ ModalPopup {
|
|||
|
||||
Item {
|
||||
Connections {
|
||||
target: RootStore.customTokenList
|
||||
target: RootStore.walletTokensModule
|
||||
onTokenDetailsWereResolved: {
|
||||
const jsonObj = JSON.parse(tokenDetails)
|
||||
if (jsonObj.error) {
|
||||
|
|
|
@ -17,6 +17,7 @@ QtObject {
|
|||
property string signingPhrase: walletSection.signingPhrase
|
||||
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp
|
||||
|
||||
property var walletTokensModule: walletSectionAllTokens
|
||||
property var defaultTokenList: walletSectionAllTokens.default
|
||||
property var customTokenList: walletSectionAllTokens.custom
|
||||
property var tokens: walletSectionAllTokens.all
|
||||
|
|
Loading…
Reference in New Issue