refactor: move provider logic to status-go
This commit is contained in:
parent
f0c1ad5087
commit
caa44cf5b9
|
@ -18,39 +18,6 @@ const SWARM_GATEWAY* = "swarm-gateways.net"
|
|||
logScope:
|
||||
topics = "provider-model"
|
||||
|
||||
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"])
|
||||
|
||||
type ProviderModel* = ref object
|
||||
events*: EventEmitter
|
||||
permissions*: PermissionsModel
|
||||
|
@ -62,206 +29,6 @@ proc newProviderModel*(events: EventEmitter, permissions: PermissionsModel, wall
|
|||
result.permissions = permissions
|
||||
result.wallet = wallet
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
proc process(self: ProviderModel, data: Web3SendAsyncReadOnly): string =
|
||||
if AUTH_METHODS.contains(data.payload.rpcMethod) and not self.permissions.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
|
||||
|
||||
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: ""
|
||||
}
|
||||
}
|
||||
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 = status_settings.getSetting[string](Setting.DappsAddress)
|
||||
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 = status_settings.getSetting[string](Setting.DappsAddress)
|
||||
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: ProviderModel, data: APIRequest): string =
|
||||
var value:JsonNode = case data.permission
|
||||
of Permission.Web3: %* [status_settings.getSetting[string](Setting.DappsAddress, "0x0000000000000000000000000000000000000000")]
|
||||
of Permission.ContactCode: %* status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||
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: self.permissions.addPermission(data.hostname, data.permission)
|
||||
|
||||
return $ %* {
|
||||
"type": ResponseTypes.APIResponse,
|
||||
"isAllowed": isAllowed,
|
||||
"permission": data.permission,
|
||||
"messageId": data.messageId,
|
||||
"data": value
|
||||
}
|
||||
|
||||
proc postMessage*(self: ProviderModel, 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:
|
||||
|
||||
proc ensResourceURL*(self: ProviderModel, ens: string, url: string):
|
||||
(string, string, string, string, bool) =
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import statusgo_backend/accounts as statusgo_backend_accounts
|
||||
import statusgo_backend/core as statusgo_backend_core
|
||||
import statusgo_backend/settings as statusgo_backend_settings
|
||||
import chat, accounts, wallet, wallet2, node, network, messages, contacts, profile, stickers, permissions, fleet, settings, mailservers, tokens, provider
|
||||
import chat, accounts, wallet, wallet2, node, network, messages, contacts, profile, stickers, permissions, fleet, settings, mailservers, tokens
|
||||
import notifications/os_notifications
|
||||
import ../eventemitter
|
||||
import bitops, stew/byteutils, chronicles
|
||||
|
@ -30,7 +30,6 @@ type Status* = ref object
|
|||
settings*: SettingsModel
|
||||
mailservers*: MailserversModel
|
||||
tokens*: TokensModel
|
||||
provider*: ProviderModel
|
||||
osnotifications*: OsNotifications
|
||||
keycard*: KeycardModel
|
||||
|
||||
|
@ -54,7 +53,6 @@ proc newStatusInstance*(fleetConfig: string, backendName: string = "statusgo"):
|
|||
result.settings = settings.newSettingsModel(result.events)
|
||||
result.mailservers = mailservers.newMailserversModel(result.events)
|
||||
result.tokens = tokens.newTokensModel(result.events)
|
||||
result.provider = provider.newProviderModel(result.events, result.permissions, result.wallet)
|
||||
result.osnotifications = newOsNotifications(result.events)
|
||||
result.keycard = newKeycardModel(result.backend)
|
||||
|
||||
|
|
|
@ -114,6 +114,9 @@ var NODE_CONFIG* = %* {
|
|||
"ClusterConfig": {
|
||||
"Enabled": true
|
||||
},
|
||||
"Web3ProviderConfig": {
|
||||
"Enabled": true
|
||||
},
|
||||
"DataDir": "./ethereum/mainnet",
|
||||
"EnableNTPSync": true,
|
||||
"KeyStoreDir": "./keystore",
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import json, json_serialization, strformat, chronicles
|
||||
import status_go
|
||||
import accounts
|
||||
import core
|
||||
|
||||
logScope:
|
||||
topics = "provider"
|
||||
|
||||
proc providerRequest*(requestType: string, message:string): RpcResponse[JsonNode] =
|
||||
let jsonMessage = message.parseJson
|
||||
if requestType == "web3-send-async-read-only" and jsonMessage.hasKey("payload") and jsonMessage["payload"].hasKey("password"):
|
||||
jsonMessage["payload"]["password"] = newJString(hashPassword(jsonMessage["payload"]["password"].getStr()))
|
||||
callPrivateRPC("provider_processRequest", %*[requestType, jsonMessage])
|
|
@ -1 +1 @@
|
|||
Subproject commit 31f2a0810d07399dfc23037db00ef315d43f93e8
|
||||
Subproject commit abbd796e0c56402e0723c407119cabbb9fbd5d73
|
Loading…
Reference in New Issue