250 lines
8.0 KiB
Nim
250 lines
8.0 KiB
Nim
|
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}
|
||
|
|
||
|
let response = status_go.login($payload, hashedPassword)
|
||
|
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
|
||
|
|