305 lines
11 KiB
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)
|
|
|