status-desktop/src/backend/accounts.nim

305 lines
11 KiB
Nim

import json, json_serialization, chronicles, strutils
import ./core, ./utils
import ./response_type
import status_go
export response_type
logScope:
topics = "rpc-accounts"
const NUMBER_OF_ADDRESSES_TO_GENERATE = 1
const MNEMONIC_PHRASE_LENGTH = 12
const PK_LENGTH_0X_INCLUDED = 132
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, emoji: string) {.raises: [Exception].} =
discard core.callPrivateRPC("accounts_saveAccounts", %* [
[{
"emoji": emoji,
"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 decompressPk*(publicKey: string): RpcResponse[string] =
discard
if publicKey.startsWith("0x04") and publicKey.len == PK_LENGTH_0X_INCLUDED:
# already decompressed
result.result = publicKey
return
var response = status_go.multiformatDeserializePublicKey(publicKey, "f")
# json response indicates error
try:
let jsonReponse = parseJson(response)
result.error = RpcError(message: jsonReponse["error"].getStr())
except JsonParsingError as e:
let secp256k1Code = "fe701"
response.removePrefix(secp256k1Code)
result.result = "0x" & response
proc compressPk*(publicKey: string): RpcResponse[string] =
let secp256k1Code = "0xe701"
let base58btc = "z"
var multiCodecKey = publicKey
multiCodecKey.removePrefix("0x")
multiCodecKey.insert(secp256k1Code)
let response = status_go.multiformatSerializePublicKey(multiCodecKey, base58btc)
# json response indicates error
try:
let jsonReponse = parseJson(response)
result.error = RpcError(message: jsonReponse["error"].getStr())
except JsonParsingError as e:
result.result = response
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 isAlias*(value: string): bool =
let response = status_go.isAlias(value)
let r = Json.decode(response, JsonNode)
return r["result"].getBool()
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 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 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 saveAccountAndLoginWithKeycard*(chatKey, password: string, account, subaccounts, settings, config: JsonNode):
RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.saveAccountAndLoginWithKeycard($account, password, $settings, $config, $subaccounts, chatKey)
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 convertToKeycardAccount*(keyStoreDir: string, account: JsonNode, settings: JsonNode, password: string, newPassword: string):
RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.convertToKeycardAccount(keyStoreDir, $account, $settings, password, newPassword)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "convertToKeycardAccount", exception=e.msg
raise newException(RpcException, e.msg)
proc login*(name, keyUid, hashedPassword, thumbnail, large: string, nodeCfgObj: string):
RpcResponse[JsonNode]
{.raises: [Exception].} =
try:
var payload = %* {
"name": name,
"key-uid": keyUid,
"identityImage": newJNull(),
}
if(thumbnail.len>0 and large.len > 0):
payload["identityImage"] = %* {"thumbnail": thumbnail, "large": large}
let response = status_go.loginWithConfig($payload, hashedPassword, nodeCfgObj)
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 loginWithKeycard*(chatKey, password: string, account: JsonNode): RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let response = status_go.loginWithKeycard($account, password, chatKey)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "loginWithKeycard", exception=e.msg
raise newException(RpcException, e.msg)
proc verifyAccountPassword*(address: string, password: string, keystoreDir: string):
RpcResponse[JsonNode] {.raises: [Exception].} =
try:
let hashedPassword = hashPassword(password)
let response = status_go.verifyAccountPassword(keystoreDir, address, hashedPassword)
result.result = Json.decode(response, JsonNode)
except RpcException as e:
error "error doing rpc request", methodName = "verifyAccountPassword", exception=e.msg
raise newException(RpcException, e.msg)
proc storeIdentityImage*(keyUID: string, imagePath: string, aX, aY, bX, bY: int):
RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [keyUID, imagePath, aX, aY, bX, bY]
result = core.callPrivateRPC("multiaccounts_storeIdentityImage", payload)
proc deleteIdentityImage*(keyUID: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [keyUID]
result = core.callPrivateRPC("multiaccounts_deleteIdentityImage", payload)
proc setDisplayName*(displayName: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [displayName]
result = core.callPrivateRPC("setDisplayName".prefix, payload)
proc getDerivedAddressList*(password: string, derivedFrom: string, path: string, pageSize: int = 0, pageNumber: int = 6,): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [password, derivedFrom, path, pageSize, pageNumber ]
result = core.callPrivateRPC("wallet_getDerivedAddressesForPath", payload)
proc getDerivedAddressListForMnemonic*(mnemonic: string, path: string, pageSize: int = 0, pageNumber: int = 6,): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [mnemonic, path, pageSize, pageNumber ]
result = core.callPrivateRPC("wallet_getDerivedAddressesForMnemonicWithPath", payload)
proc getDerivedAddressForPrivateKey*(privateKey: string,): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [privateKey]
result = core.callPrivateRPC("wallet_getDerivedAddressForPrivateKey", payload)