refactor!: provider transactions
This commit is contained in:
parent
c06c9dbc6d
commit
1989ad7971
|
@ -15,6 +15,8 @@ import ../../app_service/service/bookmarks/service as bookmark_service
|
|||
import ../../app_service/service/dapp_permissions/service as dapp_permissions_service
|
||||
import ../../app_service/service/mnemonic/service as mnemonic_service
|
||||
import ../../app_service/service/privacy/service as privacy_service
|
||||
import ../../app_service/service/provider/service as provider_service
|
||||
import ../../app_service/service/ens/service as ens_service
|
||||
|
||||
import ../core/local_account_settings
|
||||
import ../../app_service/service/profile/service as profile_service
|
||||
|
@ -75,6 +77,8 @@ type
|
|||
settingService: setting_service.Service
|
||||
bookmarkService: bookmark_service.Service
|
||||
dappPermissionsService: dapp_permissions_service.Service
|
||||
ensService: ens_service.Service
|
||||
providerService: provider_service.Service
|
||||
profileService: profile_service.Service
|
||||
settingsService: settings_service.Service
|
||||
aboutService: about_service.Service
|
||||
|
@ -142,6 +146,8 @@ proc newAppController*(appService: AppService): AppController =
|
|||
result.languageService = language_service.newService()
|
||||
result.mnemonicService = mnemonic_service.newService()
|
||||
result.privacyService = privacy_service.newService()
|
||||
result.ensService = ens_service.newService()
|
||||
result.providerService = provider_service.newService(result.dappPermissionsService, result.settingsService, result.ensService)
|
||||
|
||||
# Core
|
||||
result.localAppSettingsVariant = newQVariant(singletonInstance.localAppSettings)
|
||||
|
@ -175,7 +181,8 @@ proc newAppController*(appService: AppService): AppController =
|
|||
result.dappPermissionsService,
|
||||
result.languageService,
|
||||
result.mnemonicService,
|
||||
result.privacyService
|
||||
result.privacyService,
|
||||
result.providerService,
|
||||
)
|
||||
|
||||
#################################################
|
||||
|
@ -225,6 +232,8 @@ proc delete*(self: AppController) =
|
|||
self.walletAccountService.delete
|
||||
self.aboutService.delete
|
||||
self.dappPermissionsService.delete
|
||||
self.providerService.delete
|
||||
self.ensService.delete
|
||||
|
||||
proc startupDidLoad*(self: AppController) =
|
||||
#################################################
|
||||
|
@ -269,6 +278,8 @@ proc load*(self: AppController) =
|
|||
self.tokenService.init()
|
||||
self.settingsService.init()
|
||||
self.dappPermissionsService.init()
|
||||
self.ensService.init()
|
||||
self.providerService.init()
|
||||
self.walletAccountService.init()
|
||||
self.transactionService.init()
|
||||
self.mainModule.load()
|
||||
|
|
|
@ -68,11 +68,6 @@ QtObject:
|
|||
proc revokeAllPermissions(self: View) {.slot.} =
|
||||
self.delegate.revokeAllPermissions()
|
||||
|
||||
proc ensResourceURL*(self: View, ens: string, url: string): string {.slot.} =
|
||||
discard # TODO:
|
||||
#let (url, base, http_scheme, path_prefix, hasContentHash) = self.status.provider.ensResourceURL(ens, url)
|
||||
#result = url_replaceHostAndAddPath(url, (if hasContentHash: base else: url_host(base)), http_scheme, path_prefix)
|
||||
|
||||
proc clearDapps*(self: View) =
|
||||
self.dappsModel.clear()
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import dapps/module as dapps_module
|
|||
import ../../../../app_service/service/bookmarks/service as bookmark_service
|
||||
import ../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../app_service/service/dapp_permissions/service as dapp_permissions_service
|
||||
import ../../../../app_service/service/provider/service as provider_service
|
||||
export io_interface
|
||||
|
||||
type
|
||||
|
@ -21,13 +22,17 @@ type
|
|||
bookmarkModule: bookmark_module.AccessInterface
|
||||
dappsModule: dapps_module.AccessInterface
|
||||
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface, bookmarkService: bookmark_service.ServiceInterface, settingsService: settings_service.ServiceInterface, dappPermissionsService: dapp_permissions_service.ServiceInterface): Module =
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface,
|
||||
bookmarkService: bookmark_service.ServiceInterface,
|
||||
settingsService: settings_service.ServiceInterface,
|
||||
dappPermissionsService: dapp_permissions_service.ServiceInterface,
|
||||
providerService: provider_service.ServiceInterface): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.view = view.newView(result)
|
||||
result.viewVariant = newQVariant(result.view)
|
||||
result.moduleLoaded = false
|
||||
result.providerModule = provider_module.newModule(result, settingsService)
|
||||
result.providerModule = provider_module.newModule(result, settingsService, dappPermissionsService, providerService)
|
||||
result.bookmarkModule = bookmark_module.newModule(result, bookmarkService)
|
||||
result.dappsModule = dapps_module.newModule(result, dappPermissionsService)
|
||||
|
||||
|
@ -72,4 +77,3 @@ method dappsDidLoad*(self: Module) =
|
|||
|
||||
method viewDidLoad*(self: Module) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
import Tables
|
||||
import result
|
||||
import controller_interface
|
||||
import io_interface
|
||||
|
||||
import ../../../../../app_service/service/settings/service as settings_service
|
||||
|
||||
import ../../../../../app_service/service/dapp_permissions/service as dapp_permissions_service
|
||||
import ../../../../../app_service/service/provider/service as provider_service
|
||||
export controller_interface
|
||||
|
||||
type
|
||||
Controller* = ref object of controller_interface.AccessInterface
|
||||
delegate: io_interface.AccessInterface
|
||||
settingsService: settings_service.ServiceInterface
|
||||
dappPermissionsService: dapp_permissions_service.ServiceInterface
|
||||
providerService: provider_service.ServiceInterface
|
||||
|
||||
proc newController*(delegate: io_interface.AccessInterface,
|
||||
settingsService: settings_service.ServiceInterface):
|
||||
proc newController*(delegate: io_interface.AccessInterface,
|
||||
settingsService: settings_service.ServiceInterface,
|
||||
dappPermissionsService: dapp_permissions_service.ServiceInterface,
|
||||
providerService: provider_service.ServiceInterface):
|
||||
Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.settingsService = settingsService
|
||||
result.dappPermissionsService = dappPermissionsService
|
||||
result.providerService = providerService
|
||||
|
||||
method delete*(self: Controller) =
|
||||
discard
|
||||
|
@ -33,4 +39,16 @@ method setDappsAddress*(self: Controller, address: string) =
|
|||
self.delegate.onDappAddressChanged(address)
|
||||
|
||||
method getCurrentNetworkDetails*(self: Controller): NetworkDetails =
|
||||
return self.settingsService.getCurrentNetworkDetails()
|
||||
return self.settingsService.getCurrentNetworkDetails()
|
||||
|
||||
method disconnect*(self: Controller) =
|
||||
discard self.dappPermissionsService.revoke("web3".toPermission())
|
||||
|
||||
method postMessage*(self: Controller, message: string): string =
|
||||
return self.providerService.postMessage(message)
|
||||
|
||||
method hasPermission*(self: Controller, hostname: string, permission: string): bool =
|
||||
return self.dappPermissionsService.hasPermission(hostname, permission.toPermission())
|
||||
|
||||
method ensResourceURL*(self: Controller, ens: string, url: string): (string, string, string, string, bool) =
|
||||
return self.providerService.ensResourceURL(ens, url)
|
||||
|
|
|
@ -18,3 +18,15 @@ method setDappsAddress*(self: AccessInterface, address: string) {.base.} =
|
|||
|
||||
method getCurrentNetworkDetails*(self: AccessInterface): NetworkDetails {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method disconnect*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method postMessage*(self: AccessInterface, message: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method hasPermission*(self: AccessInterface, hostname: string, permission: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method ensResourceURL*(self: AccessInterface, ens: string, url: string): (string, string, string, string, bool) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -4,6 +4,8 @@ import view
|
|||
import controller
|
||||
import ../io_interface as delegate_interface
|
||||
import ../../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../../app_service/service/dapp_permissions/service as dapp_permissions_service
|
||||
import ../../../../../app_service/service/provider/service as provider_service
|
||||
import ../../../../core/global_singleton
|
||||
export io_interface
|
||||
|
||||
|
@ -15,13 +17,16 @@ type
|
|||
moduleLoaded: bool
|
||||
controller: controller.AccessInterface
|
||||
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface, settingsService: settings_service.ServiceInterface): Module =
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface,
|
||||
settingsService: settings_service.ServiceInterface,
|
||||
dappPermissionsService: dapp_permissions_service.ServiceInterface,
|
||||
providerService: provider_service.ServiceInterface): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.view = newView(result)
|
||||
result.viewVariant = newQVariant(result.view)
|
||||
result.moduleLoaded = false
|
||||
result.controller = controller.newController(result, settingsService)
|
||||
result.controller = controller.newController(result, settingsService, dappPermissionsService, providerService)
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.controller.delete
|
||||
|
@ -49,3 +54,15 @@ proc checkIfModuleDidLoad(self: Module) =
|
|||
|
||||
method viewDidLoad*(self: Module) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
method disconnect*(self: Module) =
|
||||
self.controller.disconnect()
|
||||
|
||||
method postMessage*(self: Module, message: string): string =
|
||||
return self.controller.postMessage(message)
|
||||
|
||||
method hasPermission*(self: Module, hostname: string, permission: string): bool =
|
||||
return self.controller.hasPermission(hostname, permission)
|
||||
|
||||
method ensResourceURL*(self: Module, ens: string, url: string): (string, string, string, string, bool) =
|
||||
return self.controller.ensResourceURL(ens, url)
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
method setDappsAddress*(self: AccessInterface, newDappAddress: string) =
|
||||
method setDappsAddress*(self: AccessInterface, newDappAddress: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onDappAddressChanged*(self: AccessInterface, newDappAddress: string) =
|
||||
method onDappAddressChanged*(self: AccessInterface, newDappAddress: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method disconnect*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method postMessage*(self: AccessInterface, message: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method hasPermission*(self: AccessInterface, hostname: string, permission: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method ensResourceURL*(self: AccessInterface, ens: string, url: string): (string, string, string, string, bool) =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -56,3 +56,16 @@ QtObject:
|
|||
proc getHost*(self: View, url: string): string {.slot.} =
|
||||
result = url_host(url)
|
||||
|
||||
proc disconnect*(self: View) {.slot.} =
|
||||
self.delegate.disconnect()
|
||||
|
||||
proc postMessage*(self: View, message: string): string {.slot.} =
|
||||
return self.delegate.postMessage(message)
|
||||
|
||||
proc hasPermission(self: View, hostname: string, permission: string): bool {.slot.} =
|
||||
return self.delegate.hasPermission(hostname, permission)
|
||||
|
||||
proc ensResourceURL*(self: View, ens: string, url: string): string {.slot.} =
|
||||
let (url, base, http_scheme, path_prefix, hasContentHash) = self.delegate.ensResourceURL(ens, url)
|
||||
result = url_replaceHostAndAddPath(url, (if hasContentHash: base else: url_host(base)), http_scheme, path_prefix)
|
||||
|
||||
|
|
|
@ -18,4 +18,4 @@ method checkForStoringPassword*(self: AccessInterface) {.base.} =
|
|||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method storePassword*(self: AccessInterface, password: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -19,6 +19,7 @@ import ../../../app_service/service/wallet_account/service as wallet_account_ser
|
|||
import ../../../app_service/service/setting/service as setting_service
|
||||
import ../../../app_service/service/bookmarks/service as bookmark_service
|
||||
import ../../../app_service/service/dapp_permissions/service as dapp_permissions_service
|
||||
import ../../../app_service/service/provider/service as provider_service
|
||||
|
||||
import eventemitter
|
||||
import ../../../app_service/service/profile/service as profile_service
|
||||
|
@ -75,7 +76,8 @@ proc newModule*[T](
|
|||
dappPermissionsService: dapp_permissions_service.ServiceInterface,
|
||||
languageService: language_service.ServiceInterface,
|
||||
mnemonicService: mnemonic_service.ServiceInterface,
|
||||
privacyService: privacy_service.ServiceInterface
|
||||
privacyService: privacy_service.ServiceInterface,
|
||||
providerService: provider_service.ServiceInterface
|
||||
): Module[T] =
|
||||
result = Module[T]()
|
||||
result.delegate = delegate
|
||||
|
@ -105,8 +107,8 @@ proc newModule*[T](
|
|||
settingService
|
||||
)
|
||||
|
||||
result.browserSectionModule = browser_section_module.newModule(result, bookmarkService, settingsService, dappPermissionsService)
|
||||
result.profileSectionModule = profile_section_module.newModule(result,events, accountsService, settingsService, profileService, contactsService, aboutService, languageService, mnemonicService, privacyService)
|
||||
result.browserSectionModule = browser_section_module.newModule(result, bookmarkService, settingsService, dappPermissionsService, providerService)
|
||||
result.profileSectionModule = profile_section_module.newModule(result, events, accountsService, settingsService, profileService, contactsService, aboutService, languageService, mnemonicService, privacyService)
|
||||
|
||||
method delete*[T](self: Module[T]) =
|
||||
self.chatSectionModule.delete
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import NimQml, chronicles
|
||||
import status/status
|
||||
import view
|
||||
|
||||
logScope:
|
||||
topics = "web3-provider"
|
||||
|
||||
type Web3ProviderController* = ref object
|
||||
status*: Status
|
||||
view*: Web3ProviderView
|
||||
variant*: QVariant
|
||||
|
||||
proc newController*(status: Status): Web3ProviderController =
|
||||
result = Web3ProviderController()
|
||||
result.status = status
|
||||
result.view = newWeb3ProviderView(status)
|
||||
result.variant = newQVariant(result.view)
|
||||
|
||||
proc delete*(self: Web3ProviderController) =
|
||||
delete self.variant
|
||||
delete self.view
|
||||
|
||||
proc init*(self: Web3ProviderController) =
|
||||
discard
|
|
@ -1,42 +0,0 @@
|
|||
import NimQml
|
||||
import status/[status, ens, chat/stickers, wallet, settings, provider]
|
||||
import status/types/[setting, permission]
|
||||
import json, json_serialization, sets, strutils
|
||||
import chronicles
|
||||
import stew/byteutils
|
||||
|
||||
logScope:
|
||||
topics = "provider-view"
|
||||
|
||||
QtObject:
|
||||
type Web3ProviderView* = ref object of QObject
|
||||
status*: Status
|
||||
|
||||
proc setup(self: Web3ProviderView) =
|
||||
self.QObject.setup
|
||||
|
||||
proc delete*(self: Web3ProviderView) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newWeb3ProviderView*(status: Status): Web3ProviderView =
|
||||
new(result, delete)
|
||||
result = Web3ProviderView()
|
||||
result.status = status
|
||||
result.setup
|
||||
|
||||
proc disconnect*(self: Web3ProviderView) {.slot.} =
|
||||
self.status.permissions.revoke("web3".toPermission())
|
||||
|
||||
proc postMessage*(self: Web3ProviderView, message: string): string {.slot.} =
|
||||
result = self.status.provider.postMessage(message)
|
||||
|
||||
proc hasPermission*(self: Web3ProviderView, hostname: string, permission: string): bool {.slot.} =
|
||||
result = self.status.permissions.hasPermission(hostname, permission.toPermission())
|
||||
|
||||
proc clearPermissions*(self: Web3ProviderView): string {.slot.} =
|
||||
self.status.permissions.clearPermissions()
|
||||
|
||||
proc ensResourceURL*(self: Web3ProviderView, ens: string, url: string): string {.slot.} =
|
||||
let (url, base, http_scheme, path_prefix, hasContentHash) = self.status.provider.ensResourceURL(ens, url)
|
||||
result = url_replaceHostAndAddPath(url, (if hasContentHash: base else: url_host(base)), http_scheme, path_prefix)
|
||||
|
|
@ -88,8 +88,10 @@ method revoke*(self: Service, dapp: string, permission: Permission): bool =
|
|||
method addPermission*(self: Service, dapp: string, permission: Permission): R =
|
||||
try:
|
||||
if not self.dapps.hasKey(dapp):
|
||||
result.err "not found"
|
||||
return
|
||||
self.dapps[dapp] = Dapp(
|
||||
name: dapp,
|
||||
permissions: initHashSet[Permission]()
|
||||
)
|
||||
|
||||
self.dapps[dapp].permissions.incl(permission)
|
||||
discard status_go.addDappPermissions(dapp, self.dapps[dapp].permissions.toSeq().mapIt($it))
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
import Tables, json, chronicles, strutils
|
||||
import sets
|
||||
import options
|
||||
import chronicles, libp2p/[multihash, multicodec, cid]
|
||||
import nimcrypto
|
||||
include ../../common/json_utils
|
||||
import service_interface
|
||||
import status/statusgo_backend_new/ens as status_go
|
||||
export service_interface
|
||||
|
||||
logScope:
|
||||
topics = "ens-service"
|
||||
|
||||
type
|
||||
Service* = ref object of ServiceInterface
|
||||
|
||||
method delete*(self: Service) =
|
||||
discard
|
||||
|
||||
proc newService*(): Service =
|
||||
result = Service()
|
||||
|
||||
method init*(self: Service) =
|
||||
discard
|
||||
|
||||
method getContentHash*(self: Service, ens: string): Option[string] =
|
||||
try:
|
||||
let contentHash = status_go.contenthash(ens)
|
||||
if contentHash != "":
|
||||
return some(contentHash)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error: ", errDescription
|
||||
return none(string)
|
||||
|
||||
method decodeENSContentHash*(self: Service, value: string): tuple[ensType: ENSType, output: string] =
|
||||
if value == "":
|
||||
return (ENSType.UNKNOWN, "")
|
||||
|
||||
if value[0..5] == "e40101":
|
||||
return (ENSType.SWARM, value.split("1b20")[1])
|
||||
|
||||
if value[0..7] == "e3010170":
|
||||
try:
|
||||
let defaultCodec = parseHexInt("70") #dag-pb
|
||||
var codec = defaultCodec # no codec specified
|
||||
var codecStartIdx = 2 # idx of where codec would start if it was specified
|
||||
# handle the case when starts with 0xe30170 instead of 0xe3010170
|
||||
if value[2..5] == "0101":
|
||||
codecStartIdx = 6
|
||||
codec = parseHexInt(value[6..7])
|
||||
elif value[2..3] == "01" and value[4..5] != "12":
|
||||
codecStartIdx = 4
|
||||
codec = parseHexInt(value[4..5])
|
||||
|
||||
# strip the info we no longer need
|
||||
var multiHashStr = value[codecStartIdx + 2..<value.len]
|
||||
|
||||
# The rest of the hash identifies the multihash algo, length, and digest
|
||||
# More info: https://multiformats.io/multihash/
|
||||
# 12 = identifies sha2-256 hash
|
||||
# 20 = multihash length = 32
|
||||
# ...rest = multihash digest
|
||||
let
|
||||
multiHash = MultiHash.init(nimcrypto.fromHex(multiHashStr)).get()
|
||||
decoded = Cid.init(CIDv0, MultiCodec.codec(codec), multiHash).get()
|
||||
return (ENSType.IPFS, $decoded)
|
||||
except Exception as e:
|
||||
error "Error decoding ENS contenthash", hash=value, exception=e.msg
|
||||
raise
|
||||
|
||||
if value[0..8] == "e50101700":
|
||||
return (ENSType.IPNS, parseHexStr(value[12..value.len-1]))
|
||||
|
||||
return (ENSType.UNKNOWN, "")
|
|
@ -0,0 +1,24 @@
|
|||
import options
|
||||
|
||||
type
|
||||
ENSType* {.pure.} = enum
|
||||
IPFS,
|
||||
SWARM,
|
||||
IPNS,
|
||||
UNKNOWN
|
||||
|
||||
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 getContentHash*(self: ServiceInterface, ens: string): Option[string] {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method decodeENSContentHash*(self: ServiceInterface, value: string): tuple[ensType: ENSType, output: string] =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -0,0 +1,324 @@
|
|||
import Tables, json, sequtils, chronicles
|
||||
import sets
|
||||
import options
|
||||
import strutils
|
||||
include ../../common/json_utils
|
||||
import ../dapp_permissions/service as dapp_permissions_service
|
||||
import ../settings/service as settings_service
|
||||
import ../ens/service as ens_service
|
||||
import service_interface
|
||||
import status/statusgo_backend_new/permissions as status_go_permissions
|
||||
import status/statusgo_backend_new/accounts as status_go_accounts
|
||||
import status/statusgo_backend_new/core as status_go_core
|
||||
from stew/base32 import nil
|
||||
from stew/base58 import nil
|
||||
import stew/byteutils
|
||||
export service_interface
|
||||
|
||||
logScope:
|
||||
topics = "provider-service"
|
||||
|
||||
const HTTPS_SCHEME* = "https"
|
||||
const IPFS_GATEWAY* = ".infura.status.im"
|
||||
const SWARM_GATEWAY* = "swarm-gateways.net"
|
||||
|
||||
type
|
||||
RequestTypes {.pure.} = enum
|
||||
Web3SendAsyncReadOnly = "web3-send-async-read-only",
|
||||
HistoryStateChanged = "history-state-changed",
|
||||
APIRequest = "api-request"
|
||||
Unknown = "unknown"
|
||||
|
||||
ResponseTypes {.pure.} = enum
|
||||
Web3SendAsyncCallback = "web3-send-async-callback",
|
||||
APIResponse = "api-response",
|
||||
Web3ResponseError = "web3-response-error"
|
||||
|
||||
type
|
||||
Payload = ref object
|
||||
id: JsonNode
|
||||
rpcMethod: string
|
||||
|
||||
Web3SendAsyncReadOnly = ref object
|
||||
messageId: JsonNode
|
||||
payload: Payload
|
||||
request: string
|
||||
hostname: string
|
||||
|
||||
APIRequest = ref object
|
||||
isAllowed: bool
|
||||
messageId: JsonNode
|
||||
permission: Permission
|
||||
hostname: string
|
||||
|
||||
const AUTH_METHODS = toHashSet(["eth_accounts", "eth_coinbase", "eth_sendTransaction", "eth_sign", "keycard_signTypedData", "eth_signTypedData", "eth_signTypedData_v3", "personal_sign", "personal_ecRecover"])
|
||||
const SIGN_METHODS = toHashSet(["eth_sign", "personal_sign", "eth_signTypedData", "eth_signTypedData_v3"])
|
||||
const ACC_METHODS = toHashSet(["eth_accounts", "eth_coinbase"])
|
||||
|
||||
proc requestType(message: string): RequestTypes =
|
||||
let data = message.parseJson
|
||||
result = RequestTypes.Unknown
|
||||
try:
|
||||
result = parseEnum[RequestTypes](data["type"].getStr())
|
||||
except:
|
||||
warn "Unknown request type received", value=data["permission"].getStr()
|
||||
|
||||
|
||||
proc toWeb3SendAsyncReadOnly(message: string): Web3SendAsyncReadOnly =
|
||||
let data = message.parseJson
|
||||
result = Web3SendAsyncReadOnly(
|
||||
messageId: data["messageId"],
|
||||
request: $data["payload"],
|
||||
hostname: data{"hostname"}.getStr(),
|
||||
payload: Payload(
|
||||
id: data["payload"]{"id"},
|
||||
rpcMethod: data["payload"]["method"].getStr()
|
||||
)
|
||||
)
|
||||
|
||||
proc toAPIRequest(message: string): APIRequest =
|
||||
let data = message.parseJson
|
||||
|
||||
result = APIRequest(
|
||||
messageId: data["messageId"],
|
||||
isAllowed: data{"isAllowed"}.getBool(),
|
||||
permission: data["permission"].getStr().toPermission(),
|
||||
hostname: data{"hostname"}.getStr()
|
||||
)
|
||||
|
||||
|
||||
|
||||
type
|
||||
Service* = ref object of service_interface.ServiceInterface
|
||||
dappPermissionsService: dapp_permissions_service.ServiceInterface
|
||||
settingsService: settings_service.ServiceInterface
|
||||
ensService: ens_service.ServiceInterface
|
||||
|
||||
method delete*(self: Service) =
|
||||
discard
|
||||
|
||||
proc newService*(dappPermissionsService: dapp_permissions_service.ServiceInterface,
|
||||
settingsService: settings_service.ServiceInterface,
|
||||
ensService: ens_service.ServiceInterface): Service =
|
||||
result = Service()
|
||||
result.dappPermissionsService = dappPermissionsService
|
||||
result.settingsService = settingsService
|
||||
result.ensService = ensService
|
||||
|
||||
method init*(self: Service) =
|
||||
discard
|
||||
|
||||
proc process(self: Service, data: Web3SendAsyncReadOnly): string =
|
||||
if AUTH_METHODS.contains(data.payload.rpcMethod) and not self.dappPermissionsService.hasPermission(data.hostname, Permission.Web3):
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": {
|
||||
"code": 4100
|
||||
}
|
||||
}
|
||||
|
||||
if data.payload.rpcMethod == "eth_sendTransaction":
|
||||
try:
|
||||
let request = data.request.parseJson
|
||||
let fromAddress = request["params"][0]["from"].getStr()
|
||||
let to = request["params"][0]{"to"}.getStr()
|
||||
let value = if (request["params"][0]["value"] != nil):
|
||||
request["params"][0]["value"].getStr()
|
||||
else:
|
||||
"0"
|
||||
let password = request["password"].getStr()
|
||||
let selectedGasLimit = request["selectedGasLimit"].getStr()
|
||||
let selectedGasPrice = request["selectedGasPrice"].getStr()
|
||||
let selectedTipLimit = request{"selectedTipLimit"}.getStr()
|
||||
let selectedOverallLimit = request{"selectedOverallLimit"}.getStr()
|
||||
let txData = if (request["params"][0].hasKey("data") and request["params"][0]["data"].kind != JNull):
|
||||
request["params"][0]["data"].getStr()
|
||||
else:
|
||||
""
|
||||
|
||||
var success: bool
|
||||
var errorMessage = ""
|
||||
var response = ""
|
||||
var validInput: bool = true
|
||||
|
||||
|
||||
# TODO: use the transaction service to send the trx
|
||||
|
||||
#[
|
||||
let eip1559Enabled = self.wallet.isEIP1559Enabled()
|
||||
|
||||
try:
|
||||
validateTransactionInput(fromAddress, to, "", value, selectedGasLimit, selectedGasPrice, txData, eip1559Enabled, selectedTipLimit, selectedOverallLimit, "dummy")
|
||||
except Exception as e:
|
||||
validInput = false
|
||||
success = false
|
||||
errorMessage = e.msg
|
||||
|
||||
if validInput:
|
||||
# TODO make this async
|
||||
response = wallet.sendTransaction(fromAddress, to, value, selectedGasLimit, selectedGasPrice, eip1559Enabled, selectedTipLimit, selectedOverallLimit, password, success, txData)
|
||||
errorMessage = if not success:
|
||||
if response == "":
|
||||
"web3-response-error"
|
||||
else:
|
||||
response
|
||||
else:
|
||||
""
|
||||
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": errorMessage,
|
||||
"result": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": data.payload.id,
|
||||
"result": if (success): response else: ""
|
||||
}
|
||||
}
|
||||
|
||||
]#
|
||||
# TODO: delete this:
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": "",
|
||||
"result": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": data.payload.id,
|
||||
"result": ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
except Exception as e:
|
||||
error "Error sending the transaction", msg = e.msg
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": {
|
||||
"code": 4100,
|
||||
"message": e.msg
|
||||
}
|
||||
}
|
||||
|
||||
if SIGN_METHODS.contains(data.payload.rpcMethod):
|
||||
try:
|
||||
let request = data.request.parseJson
|
||||
var params = request["params"]
|
||||
let password = hashPassword(request["password"].getStr())
|
||||
let dappAddress = self.settingsService.getDappsAddress()
|
||||
var rpcResult = "{}"
|
||||
|
||||
case data.payload.rpcMethod:
|
||||
of "eth_signTypedData", "eth_signTypedData_v3":
|
||||
rpcResult = signTypedData(params[1].getStr(), dappAddress, password)
|
||||
else:
|
||||
rpcResult = signMessage($ %* {
|
||||
"data": params[0].getStr(),
|
||||
"password": password,
|
||||
"account": dappAddress
|
||||
})
|
||||
|
||||
let jsonRpcResult = rpcResult.parseJson
|
||||
let success: bool = not jsonRpcResult.hasKey("error")
|
||||
let errorMessage = if success: "" else: jsonRpcResult["error"]{"message"}.getStr()
|
||||
let response = if success: jsonRpcResult["result"].getStr() else: ""
|
||||
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": errorMessage,
|
||||
"result": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": if data.payload.id == nil: newJNull() else: data.payload.id,
|
||||
"result": if (success): response else: ""
|
||||
}
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error "Error signing message", msg = e.msg
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": {
|
||||
"code": 4100,
|
||||
"message": e.msg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ACC_METHODS.contains(data.payload.rpcMethod):
|
||||
let dappAddress = self.settingsService.getDappsAddress()
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"result": {
|
||||
"jsonrpc": "2.0",
|
||||
"id": data.payload.id,
|
||||
"result": if data.payload.rpcMethod == "eth_coinbase": newJString(dappAddress) else: %*[dappAddress]
|
||||
}
|
||||
}
|
||||
|
||||
let rpcResult = callRPC(data.request)
|
||||
|
||||
return $ %* {
|
||||
"type": ResponseTypes.Web3SendAsyncCallback,
|
||||
"messageId": data.messageId,
|
||||
"error": (if rpcResult == "": newJString("web3-response-error") else: newJNull()),
|
||||
"result": rpcResult.parseJson
|
||||
}
|
||||
|
||||
proc process(self: Service, data: APIRequest): string =
|
||||
var value:JsonNode = case data.permission
|
||||
of Permission.Web3: %* [self.settingsService.getDappsAddress()]
|
||||
of Permission.ContactCode: %* self.settingsService.getPubKey()
|
||||
of Permission.Unknown: newJNull()
|
||||
|
||||
let isAllowed = data.isAllowed and data.permission != Permission.Unknown
|
||||
|
||||
info "API request received", host=data.hostname, value=data.permission, isAllowed
|
||||
|
||||
if isAllowed:
|
||||
discard self.dappPermissionsService.addPermission(data.hostname, data.permission)
|
||||
|
||||
return $ %* {
|
||||
"type": ResponseTypes.APIResponse,
|
||||
"isAllowed": isAllowed,
|
||||
"permission": data.permission,
|
||||
"messageId": data.messageId,
|
||||
"data": value
|
||||
}
|
||||
|
||||
method postMessage*(self: Service, message: string): string =
|
||||
case message.requestType():
|
||||
of RequestTypes.Web3SendAsyncReadOnly: self.process(message.toWeb3SendAsyncReadOnly())
|
||||
of RequestTypes.HistoryStateChanged: """{"type":"TODO-IMPLEMENT-THIS"}""" ############# TODO:
|
||||
of RequestTypes.APIRequest: self.process(message.toAPIRequest())
|
||||
else: """{"type":"TODO-IMPLEMENT-THIS"}""" ##################### TODO:
|
||||
|
||||
method ensResourceURL*(self: Service, ens: string, url: string): (string, string, string, string, bool) =
|
||||
let contentHash = self.ensService.getContentHash(ens)
|
||||
if contentHash.isNone(): # ENS does not have a content hash
|
||||
return (url, url, HTTPS_SCHEME, "", false)
|
||||
|
||||
let decodedHash = self.ensService.decodeENSContentHash(contentHash.get())
|
||||
|
||||
case decodedHash[0]:
|
||||
of ENSType.IPFS:
|
||||
let
|
||||
base58bytes = base58.decode(base58.BTCBase58, decodedHash[1])
|
||||
base32Hash = base32.encode(base32.Base32Lower, base58bytes)
|
||||
|
||||
result = (url, base32Hash & IPFS_GATEWAY, HTTPS_SCHEME, "", true)
|
||||
|
||||
of ENSType.SWARM:
|
||||
result = (url, SWARM_GATEWAY, HTTPS_SCHEME,
|
||||
"/bzz:/" & decodedHash[1] & "/", true)
|
||||
|
||||
of ENSType.IPNS:
|
||||
result = (url, decodedHash[1], HTTPS_SCHEME, "", true)
|
||||
|
||||
else:
|
||||
warn "Unknown content for", ens, contentHash
|
|
@ -0,0 +1,15 @@
|
|||
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 postMessage*(self: ServiceInterface, message: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method ensResourceURL*(self: ServiceInterface, ens: string, url: string): (string, string, string, string, bool) =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -5,7 +5,6 @@ import app/wallet/v1/core as wallet
|
|||
import app/wallet/v2/core as walletV2
|
||||
import app/node/core as node
|
||||
import app/utilsView/core as utilsView
|
||||
import app/provider/core as provider
|
||||
import app/keycard/core as keycard
|
||||
import status/types/[account]
|
||||
import status_go
|
||||
|
@ -158,10 +157,6 @@ proc mainProc() =
|
|||
defer: utilsController.delete()
|
||||
singletonInstance.engine.setRootContextProperty("utilsModel", utilsController.variant)
|
||||
|
||||
var provider = provider.newController(status)
|
||||
defer: provider.delete()
|
||||
singletonInstance.engine.setRootContextProperty("web3Provider", provider.variant)
|
||||
|
||||
var keycard = keycard.newController(status)
|
||||
defer: keycard.delete()
|
||||
|
||||
|
@ -172,7 +167,6 @@ proc mainProc() =
|
|||
status.startMessenger()
|
||||
wallet.init()
|
||||
wallet2.init()
|
||||
provider.init()
|
||||
chat.init()
|
||||
utilsController.init()
|
||||
node.init()
|
||||
|
|
|
@ -12,7 +12,7 @@ QtObject {
|
|||
var url = RootStore.getUrlFromUserInput(text);
|
||||
var host = providerModule.getHost(url);
|
||||
if(host.endsWith(".eth")){
|
||||
var ensResource = web3Provider.ensResourceURL(host, url);
|
||||
var ensResource = providerModule.ensResourceURL(host, url);
|
||||
|
||||
if(/^https\:\/\/swarm\-gateways\.net\/bzz:\/([0-9a-fA-F]{64}|.+\.eth)(\/?)/.test(ensResource)){
|
||||
// TODO: populate urlENSDictionary for prettier url instead of swarm-gateway big URL
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit fb58ecc10afe13013865163b74563ae762e808f5
|
||||
Subproject commit 845c29b6be236bf9a0459cff0d2abd57aec8053c
|
Loading…
Reference in New Issue