status-lib/status/statusgo_backend_new/accounts.nim

264 lines
8.5 KiB
Nim
Raw Normal View History

import json, json_serialization, chronicles, nimcrypto
import ./core, ./utils
import ./response_type
import status_go
export response_type
logScope:
topics = "rpc-accounts"
const NUMBER_OF_ADDRESSES_TO_GENERATE = 5
const MNEMONIC_PHRASE_LENGTH = 12
const GENERATED* = "generated"
const SEED* = "seed"
const KEY* = "key"
const WATCH* = "watch"
proc getAccounts*(): RpcResponse[JsonNode] {.raises: [Exception].} =
return core.callPrivateRPC("accounts_getAccounts")
proc deleteAccount*(address: string): RpcResponse[JsonNode] {.raises: [Exception].} =
return core.callPrivateRPC("accounts_deleteAccount", %* [address])
proc updateAccount*(name, address, publicKey, walletType, color: string) {.raises: [Exception].} =
discard core.callPrivateRPC("accounts_saveAccounts", %* [
[{
"color": color,
"name": name,
"address": address,
"public-key": publicKey,
"type": walletType,
"path": "m/44'/60'/0'/0/1" # <--- TODO: fix this. Derivation path is not supposed to change
}]
])
proc generateAddresses*(paths: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* {
"n": NUMBER_OF_ADDRESSES_TO_GENERATE,
"mnemonicPhraseLength": MNEMONIC_PHRASE_LENGTH,
"bip39Passphrase": "",
"paths": paths
}
try:
let response = status_go.multiAccountGenerateAndDeriveAddresses($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "generateAddresses", exception=e.msg
raise newException(RpcException, e.msg)
proc generateAlias*(publicKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.generateAlias(publicKey)
result.result = %* response
except RpcException as e:
error "error doing rpc request", methodName = "generateAlias", exception=e.msg
raise newException(RpcException, e.msg)
proc generateIdenticon*(publicKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.identicon(publicKey)
result.result = %* response
except RpcException as e:
error "error doing rpc request", methodName = "generateIdenticon", exception=e.msg
raise newException(RpcException, e.msg)
proc multiAccountImportMnemonic*(mnemonic: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* {
"mnemonicPhrase": mnemonic,
"Bip39Passphrase": ""
}
try:
let response = status_go.multiAccountImportMnemonic($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "multiAccountImportMnemonic", exception=e.msg
raise newException(RpcException, e.msg)
proc deriveAccounts*(accountId: string, paths: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* {
"accountID": accountId,
"paths": paths
}
try:
let response = status_go.multiAccountDeriveAddresses($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "deriveAccounts", exception=e.msg
raise newException(RpcException, e.msg)
proc openedAccounts*(path: string): RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.openAccounts(path)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "openedAccounts", exception=e.msg
raise newException(RpcException, e.msg)
proc storeDerivedAccounts*(id, hashedPassword: string, paths: seq[string]):
RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* {
"accountID": id,
"paths": paths,
"password": hashedPassword
}
try:
let response = status_go.multiAccountStoreDerivedAccounts($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "storeDerivedAccounts", exception=e.msg
raise newException(RpcException, e.msg)
proc storeAccounts*(id, hashedPassword: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* {
"accountID": id,
"password": hashedPassword
}
try:
let response = status_go.multiAccountStoreAccount($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "storeAccounts", exception=e.msg
raise newException(RpcException, e.msg)
proc hashPassword*(password: string): string =
result = "0x" & $keccak_256.digest(password)
proc saveAccount*(
address: string,
name: string,
password: string,
color: string,
accountType: string,
isADerivedAccount = true,
walletIndex: int = 0,
id: string = "",
publicKey: string = "",
) {.raises: [Exception].} =
var derivationPath = "m/44'/60'/0'/0/0"
let hashedPassword = hashPassword(password)
if (isADerivedAccount):
let derivationPath = (if accountType == GENERATED: "m/" else: "m/44'/60'/0'/0/") & $walletIndex
discard storeDerivedAccounts(id, hashedPassword, @[derivationPath])
elif accountType == KEY:
discard storeAccounts(id, hashedPassword)
discard callPrivateRPC("accounts_saveAccounts", %* [
[{
"color": color,
"name": name,
"address": address,
"public-key": publicKey,
"type": accountType,
"path": derivationPath
}]
])
proc loadAccount*(address: string, password: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let hashedPassword = hashPassword(password)
let payload = %* {
"address": address,
"password": hashedPassword
}
try:
let response = status_go.multiAccountLoadAccount($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "storeAccounts", exception=e.msg
raise newException(RpcException, e.msg)
proc addPeer*(peer: string): RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.addPeer(peer)
result.result = %* response
except RpcException as e:
error "error doing rpc request", methodName = "addPeer", exception=e.msg
raise newException(RpcException, e.msg)
proc saveAccountAndLogin*(hashedPassword: string, account, subaccounts, settings,
config: JsonNode): RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.saveAccountAndLogin($account, hashedPassword,
$settings, $config, $subaccounts)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "saveAccountAndLogin", exception=e.msg
raise newException(RpcException, e.msg)
proc login*(name, keyUid, hashedPassword, identicon, thumbnail, large: string):
RpcResponse[JsonNode]
{.raises: [Exception].} =
try:
var payload = %* {
"name": name,
"key-uid": keyUid,
"identityImage": newJNull(),
"identicon": identicon
}
if(thumbnail.len>0 and large.len > 0):
payload["identityImage"] = %* {"thumbnail": thumbnail, "large": large}
# TODO:
# If you added a new value in the nodeconfig in status-go, old accounts will not have this value, since the node config
# is stored in the database, and it's not easy to migrate using .sql
# While this is fixed, you can add here any missing attribute on the node config, and it will be merged with whatever
# the account has in the db
var nodeCfg = %* {
2021-12-22 15:34:31 +00:00
"Web3ProviderConfig": %* {
2021-12-21 14:06:54 +00:00
"Enabled": true
2021-12-21 15:23:35 +00:00
},
"EnsConfig": %* {
"Enabled": true
},
}
let response = status_go.loginWithConfig($payload, hashedPassword, $nodeCfg)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "login", exception=e.msg
raise newException(RpcException, e.msg)
proc multiAccountImportPrivateKey*(privateKey: string): RpcResponse[JsonNode] =
let payload = %* {
"privateKey": privateKey
}
try:
let response = status_go.multiAccountImportPrivateKey($payload)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "multiAccountImportPrivateKey", exception=e.msg
raise newException(RpcException, e.msg)
proc verifyAccountPassword*(address: string, password: string, keystoreDir: string): bool =
let hashedPassword = hashPassword(password)
let verifyResult = status_go.verifyAccountPassword(keystoreDir, address, hashedPassword)
let error = parseJson(verifyResult)["error"].getStr
if error == "":
return true
return false