Refactor/wallet part 2 (#91)
* refactor: add save account * refactor: add account generation * refactor: save settings * refactor: add update account in new be * add getTransfersByAddress (#93) Co-authored-by: Jonathan Rainville <rainville.jonathan@gmail.com>
This commit is contained in:
parent
ad9af00340
commit
76e867f1d8
|
@ -1,4 +1,4 @@
|
||||||
import json, json_serialization, chronicles
|
import json, json_serialization, chronicles, nimcrypto
|
||||||
import ./core, ./utils
|
import ./core, ./utils
|
||||||
import ./response_type
|
import ./response_type
|
||||||
|
|
||||||
|
@ -12,9 +12,29 @@ logScope:
|
||||||
const NUMBER_OF_ADDRESSES_TO_GENERATE = 5
|
const NUMBER_OF_ADDRESSES_TO_GENERATE = 5
|
||||||
const MNEMONIC_PHRASE_LENGTH = 12
|
const MNEMONIC_PHRASE_LENGTH = 12
|
||||||
|
|
||||||
|
const GENERATED* = "generated"
|
||||||
|
const SEED* = "seed"
|
||||||
|
const KEY* = "key"
|
||||||
|
const WATCH* = "watch"
|
||||||
|
|
||||||
proc getAccounts*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc getAccounts*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
return core.callPrivateRPC("accounts_getAccounts")
|
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].} =
|
proc generateAddresses*(paths: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
let payload = %* {
|
let payload = %* {
|
||||||
"n": NUMBER_OF_ADDRESSES_TO_GENERATE,
|
"n": NUMBER_OF_ADDRESSES_TO_GENERATE,
|
||||||
|
@ -102,6 +122,69 @@ proc storeDerivedAccounts*(id, hashedPassword: string, paths: seq[string]):
|
||||||
error "error doing rpc request", methodName = "storeDerivedAccounts", exception=e.msg
|
error "error doing rpc request", methodName = "storeDerivedAccounts", exception=e.msg
|
||||||
raise newException(RpcException, 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].} =
|
proc addPeer*(peer: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
try:
|
try:
|
||||||
let response = status_go.addPeer(peer)
|
let response = status_go.addPeer(peer)
|
||||||
|
@ -142,3 +225,26 @@ proc login*(name, keyUid, hashedPassword, identicon, thumbnail, large: string):
|
||||||
except RpcException as e:
|
except RpcException as e:
|
||||||
error "error doing rpc request", methodName = "login", exception=e.msg
|
error "error doing rpc request", methodName = "login", exception=e.msg
|
||||||
raise newException(RpcException, 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
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import
|
||||||
|
json, options, strutils
|
||||||
|
|
||||||
|
import
|
||||||
|
web3/[conversions, ethtypes], stint
|
||||||
|
|
||||||
|
import ../types/transaction
|
||||||
|
|
||||||
|
# TODO: make this public in nim-web3 lib
|
||||||
|
template stripLeadingZeros*(value: string): string =
|
||||||
|
var cidx = 0
|
||||||
|
# ignore the last character so we retain '0' on zero value
|
||||||
|
while cidx < value.len - 1 and value[cidx] == '0':
|
||||||
|
cidx.inc
|
||||||
|
value[cidx .. ^1]
|
||||||
|
|
||||||
|
proc `%`*(x: TransactionData): JsonNode =
|
||||||
|
result = newJobject()
|
||||||
|
result["from"] = %x.source
|
||||||
|
result["type"] = %x.txType
|
||||||
|
if x.to.isSome:
|
||||||
|
result["to"] = %x.to.unsafeGet
|
||||||
|
if x.gas.isSome:
|
||||||
|
result["gas"] = %x.gas.unsafeGet
|
||||||
|
if x.gasPrice.isSome:
|
||||||
|
result["gasPrice"] = %("0x" & x.gasPrice.unsafeGet.toHex.stripLeadingZeros)
|
||||||
|
if x.maxFeePerGas.isSome:
|
||||||
|
result["maxFeePerGas"] = %("0x" & x.maxFeePerGas.unsafeGet.toHex)
|
||||||
|
if x.maxPriorityFeePerGas.isSome:
|
||||||
|
result["maxPriorityFeePerGas"] = %("0x" & x.maxPriorityFeePerGas.unsafeGet.toHex)
|
||||||
|
if x.value.isSome:
|
||||||
|
result["value"] = %("0x" & x.value.unsafeGet.toHex)
|
||||||
|
result["data"] = %x.data
|
||||||
|
if x.nonce.isSome:
|
||||||
|
result["nonce"] = %x.nonce.unsafeGet
|
|
@ -3,6 +3,9 @@ import ./core, ./response_type
|
||||||
|
|
||||||
export response_type
|
export response_type
|
||||||
|
|
||||||
|
proc getAccounts*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
return core.callPrivateRPC("eth_accounts")
|
||||||
|
|
||||||
proc getBlockByNumber*(blockNumber: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc getBlockByNumber*(blockNumber: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
let payload = %* [blockNumber, false]
|
let payload = %* [blockNumber, false]
|
||||||
return core.callPrivateRPC("eth_getBlockByNumber", payload)
|
return core.callPrivateRPC("eth_getBlockByNumber", payload)
|
||||||
|
|
|
@ -5,3 +5,6 @@ export response_type
|
||||||
|
|
||||||
proc getSettings*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
proc getSettings*(): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
return core.callPrivateRPC("settings_getSettings")
|
return core.callPrivateRPC("settings_getSettings")
|
||||||
|
|
||||||
|
proc saveSettings*(key: string, value: string | JsonNode | bool | int) {.raises: [Exception].} =
|
||||||
|
discard core.callPrivateRPC("settings_saveSetting", %* [key, value])
|
|
@ -1,7 +1,17 @@
|
||||||
import json
|
import json, stint, chronicles, strutils, conversions
|
||||||
|
|
||||||
import ./core
|
|
||||||
|
import ../types/transaction
|
||||||
|
import ./core as core
|
||||||
|
|
||||||
proc checkRecentHistory*(addresses: seq[string]) {.raises: [Exception].} =
|
proc checkRecentHistory*(addresses: seq[string]) {.raises: [Exception].} =
|
||||||
let payload = %* [addresses]
|
let payload = %* [addresses]
|
||||||
discard callPrivateRPC("wallet_checkRecentHistory", payload)
|
discard callPrivateRPC("wallet_checkRecentHistory", payload)
|
||||||
|
|
||||||
|
proc getTransfersByAddress*(address: string, toBlock: Uint256, limit: int, loadMore: bool = false): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
let
|
||||||
|
toBlockParsed = if not loadMore: newJNull() else: %("0x" & stint.toHex(toBlock))
|
||||||
|
limitParsed = "0x" & limit.toHex.stripLeadingZeros
|
||||||
|
|
||||||
|
callPrivateRPC("wallet_getTransfersByAddress", %* [address, toBlockParsed, limitParsed, loadMore])
|
||||||
|
|
Loading…
Reference in New Issue