279 lines
9.4 KiB
Nim
279 lines
9.4 KiB
Nim
import json, json_serialization, chronicles
|
|
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 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 = %* {
|
|
"ShhextConfig": %* {
|
|
"EnableMailserverCycle": true
|
|
},
|
|
"Web3ProviderConfig": %* {
|
|
"Enabled": true
|
|
},
|
|
"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
|
|
|
|
proc generateAccount*(password, name, color: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
|
let payload = %* [hashPassword(password), name, color]
|
|
return core.callPrivateRPC("accounts_generateAccount", payload)
|
|
|
|
proc addAccountWithMnemonic*(mnemonic, password, name, color: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
|
let payload = %* [mnemonic, hashPassword(password), name, color]
|
|
return core.callPrivateRPC("accounts_addAccountWithMnemonic", payload)
|
|
|
|
proc addAccountWithPrivateKey*(privateKey, password, name, color: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
|
let payload = %* [privateKey, hashPassword(password), name, color]
|
|
return core.callPrivateRPC("accounts_addAccountWithPrivateKey", payload)
|
|
|
|
proc addAccountWatch*(address, name, color: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
|
let payload = %* [address, name, color]
|
|
return core.callPrivateRPC("accounts_addAccountWatch", payload) |