diff --git a/.gitmodules b/.gitmodules index cc3b297938..98f6abb100 100644 --- a/.gitmodules +++ b/.gitmodules @@ -106,3 +106,6 @@ [submodule "vendor/semver.nim"] path = vendor/semver.nim url = https://github.com/euantorano/semver.nim +[submodule "vendor/nim-status-lib"] + path = vendor/nim-status-lib + url = https://github.com/status-im/nim-status-lib.git diff --git a/src/app/browser/core.nim b/src/app/browser/core.nim index e89b2dbfda..115ae71d76 100644 --- a/src/app/browser/core.nim +++ b/src/app/browser/core.nim @@ -1,5 +1,5 @@ import NimQml, chronicles -import ../../status/status +import status/status import view logScope: diff --git a/src/app/browser/view.nim b/src/app/browser/view.nim index e193cacb1a..7c99b8f534 100644 --- a/src/app/browser/view.nim +++ b/src/app/browser/view.nim @@ -1,6 +1,6 @@ import NimQml, json, chronicles -import ../../status/[status, browser] -import ../../status/types/[bookmark] +import status/[status, browser] +import status/types/[bookmark] import views/bookmark_list QtObject: diff --git a/src/app/browser/views/bookmark_list.nim b/src/app/browser/views/bookmark_list.nim index 81ee30e6e7..7788f15c42 100644 --- a/src/app/browser/views/bookmark_list.nim +++ b/src/app/browser/views/bookmark_list.nim @@ -1,6 +1,6 @@ import NimQml, Tables, chronicles import sequtils as sequtils -import ../../../status/types/[bookmark] +import status/types/[bookmark] type BookmarkRoles {.pure.} = enum diff --git a/src/app/chat/core.nim b/src/app/chat/core.nim index 267dcdcf63..923bd8c792 100644 --- a/src/app/chat/core.nim +++ b/src/app/chat/core.nim @@ -1,12 +1,12 @@ import NimQml, chronicles, tables -import ../../status/chat as chat_model -import ../../status/messages as messages_model -import ../../status/[chat, contacts, status, wallet, stickers, settings] -import ../../status/types/[message, transaction, os_notification, setting] +import status/chat as chat_model +import status/messages as messages_model +import status/[chat, contacts, status, wallet, stickers, settings] +import status/types/[message, transaction, os_notification, setting] import ../../app_service/[main] -import ../../app_service/signals/[base] +import status/signals/[base] import view, views/channels_list, views/message_list, views/reactions, views/stickers as stickers_view -import ../../eventemitter +import eventemitter logScope: topics = "chat-controller" diff --git a/src/app/chat/event_handling.nim b/src/app/chat/event_handling.nim index 28e979d278..1392b36611 100644 --- a/src/app/chat/event_handling.nim +++ b/src/app/chat/event_handling.nim @@ -2,7 +2,7 @@ import # std libs strutils import # status-desktop libs - ../../status/chat/chat as status_chat, + status/chat/chat as status_chat, ./views/communities, ./views/messages import ../../app_service/tasks/[qt, threadpool] diff --git a/src/app/chat/signal_handling.nim b/src/app/chat/signal_handling.nim index 1a39ae8816..5b93561be7 100644 --- a/src/app/chat/signal_handling.nim +++ b/src/app/chat/signal_handling.nim @@ -1,7 +1,7 @@ import ../../app_service/tasks/marathon/mailserver/worker, - ../../app_service/signals/messages as signals_messages, - ../../app_service/signals/[community, discovery_summary, envelope, expired] + status/signals/messages as signals_messages, + status/signals/[community, discovery_summary, envelope, expired] proc handleSignals(self: ChatController) = self.status.events.on(SignalType.Message.event) do(e:Args): diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index a5ac96cc4c..07916c7398 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -1,20 +1,20 @@ import NimQml, Tables, json, sequtils, chronicles, strutils, os, strformat -import ../../status/[status] -import ../../status/constants -import ../../status/utils as status_utils -import ../../status/chat as status_chat -import ../../status/messages as status_messages -import ../../status/mailservers -import ../../status/contacts as status_contacts -import ../../status/ens as status_ens -import ../../status/chat/[chat] -import ../../status/profile/profile -import ../../status/types/[activity_center_notification, os_notification, rpc_response] +import status/[status] +import status/constants +import status/utils as status_utils +import status/chat as status_chat +import status/messages as status_messages +import status/mailservers +import status/contacts as status_contacts +import status/ens as status_ens +import status/chat/[chat] +import status/profile/profile +import status/types/[activity_center_notification, os_notification, rpc_response] import ../../app_service/[main] import ../../app_service/tasks/[qt, threadpool] import ../../app_service/tasks/marathon/mailserver/worker -import ../../app_service/signals/[base] -import ../../status/notifications/[os_notifications] +import status/signals/[base] +import status/notifications/[os_notifications] import ../utils/image_utils import web3/[conversions, ethtypes] import views/message_search/[view_controller] @@ -22,7 +22,7 @@ import views/[channels_list, message_list, chat_item, reactions, stickers, group # TODO: remove me -import ../../status/libstatus/chat as libstatus_chat +import status/libstatus/chat as libstatus_chat logScope: topics = "chats-view" diff --git a/src/app/chat/views/activity_notification_list.nim b/src/app/chat/views/activity_notification_list.nim index 59173ab491..813bf50814 100644 --- a/src/app/chat/views/activity_notification_list.nim +++ b/src/app/chat/views/activity_notification_list.nim @@ -1,7 +1,7 @@ import NimQml, Tables, chronicles, json, sequtils, strformat -import ../../../status/status -import ../../../status/accounts -import ../../../status/types/[activity_center_notification] +import status/status +import status/accounts +import status/types/[activity_center_notification] import strutils import message_item diff --git a/src/app/chat/views/category_item.nim b/src/app/chat/views/category_item.nim index b43f022585..498a5f28e8 100644 --- a/src/app/chat/views/category_item.nim +++ b/src/app/chat/views/category_item.nim @@ -1,5 +1,5 @@ import NimQml, std/wrapnils -import ../../../status/chat/chat +import status/chat/chat QtObject: type CategoryItemView* = ref object of QObject diff --git a/src/app/chat/views/category_list.nim b/src/app/chat/views/category_list.nim index 5866b48f3e..a5629c03b6 100644 --- a/src/app/chat/views/category_list.nim +++ b/src/app/chat/views/category_list.nim @@ -1,8 +1,8 @@ import NimQml, Tables import algorithm -import ../../../status/chat/[chat] -import ../../../status/status -import ../../../status/accounts +import status/chat/[chat] +import status/status +import status/accounts import strutils type diff --git a/src/app/chat/views/channel.nim b/src/app/chat/views/channel.nim index 714803242f..b804e3c0de 100644 --- a/src/app/chat/views/channel.nim +++ b/src/app/chat/views/channel.nim @@ -1,9 +1,9 @@ import NimQml, Tables, json, sequtils, chronicles, strutils -import ../../../status/[status, contacts] -import ../../../status/ens as status_ens -import ../../../status/chat as status_chat -import ../../../status/chat/[chat] +import status/[status, contacts] +import status/ens as status_ens +import status/chat as status_chat +import status/chat/[chat] import ../../../app_service/[main] import communities, chat_item, channels_list, communities, community_list diff --git a/src/app/chat/views/channels_list.nim b/src/app/chat/views/channels_list.nim index a6c8f9e59a..8327ff24e5 100644 --- a/src/app/chat/views/channels_list.nim +++ b/src/app/chat/views/channels_list.nim @@ -1,9 +1,9 @@ import NimQml, Tables import algorithm -import ../../../status/chat/[chat] -import ../../../status/status -import ../../../status/accounts -import ../../../status/types/[message] +import status/chat/[chat] +import status/status +import status/accounts +import status/types/[message] import strutils type diff --git a/src/app/chat/views/chat_item.nim b/src/app/chat/views/chat_item.nim index eef5512bcf..7f8643c5b7 100644 --- a/src/app/chat/views/chat_item.nim +++ b/src/app/chat/views/chat_item.nim @@ -1,7 +1,7 @@ import NimQml, Tables, std/wrapnils -import ../../../status/[chat/chat, status, ens, accounts, settings] -import ../../../status/utils as status_utils -import ../../../status/types/[setting] +import status/[chat/chat, status, ens, accounts, settings] +import status/utils as status_utils +import status/types/[setting] import chat_members diff --git a/src/app/chat/views/chat_members.nim b/src/app/chat/views/chat_members.nim index 696dc8326d..c19bef64b8 100644 --- a/src/app/chat/views/chat_members.nim +++ b/src/app/chat/views/chat_members.nim @@ -1,5 +1,5 @@ import NimQml, Tables, - ../../../status/[chat/chat, status, ens] + status/[chat/chat, status, ens] type ChatMemberRoles {.pure.} = enum diff --git a/src/app/chat/views/communities.nim b/src/app/chat/views/communities.nim index a659fd13af..cfe70a33fd 100644 --- a/src/app/chat/views/communities.nim +++ b/src/app/chat/views/communities.nim @@ -1,12 +1,12 @@ import NimQml, json, sequtils, chronicles, strutils, strformat, tables -import ../../../status/status -import ../../../status/chat/chat +import status/status +import status/chat/chat import ./community_list import ./community_item import ./community_membership_request_list import ../../utils/image_utils -import ../../../status/types/[activity_center_notification, status_update, rpc_response] -import ../../../app_service/signals/[base] +import status/types/[activity_center_notification, status_update, rpc_response] +import status/signals/[base] logScope: topics = "communities-view" diff --git a/src/app/chat/views/community_item.nim b/src/app/chat/views/community_item.nim index c79aa1c7ae..de8317aa4f 100644 --- a/src/app/chat/views/community_item.nim +++ b/src/app/chat/views/community_item.nim @@ -1,7 +1,7 @@ import NimQml, std/wrapnils, json, tables -import ../../../status/[chat/chat, status] +import status/[chat/chat, status] import channels_list -import ../../../eventemitter +import eventemitter import community_members_list import category_list, category_item import community_membership_request_list diff --git a/src/app/chat/views/community_list.nim b/src/app/chat/views/community_list.nim index b696528112..ee9767c53a 100644 --- a/src/app/chat/views/community_list.nim +++ b/src/app/chat/views/community_list.nim @@ -5,8 +5,8 @@ import # vendor libs chronicles, json_serialization import # status-desktop libs - ../../../status/chat/chat, ../../../status/status, ../../../status/accounts -import ../../../status/types/[status_update] + status/chat/chat, status/status, status/accounts +import status/types/[status_update] type CommunityRoles {.pure.} = enum diff --git a/src/app/chat/views/community_members_list.nim b/src/app/chat/views/community_members_list.nim index 48f8f1d3e7..37d8e13516 100644 --- a/src/app/chat/views/community_members_list.nim +++ b/src/app/chat/views/community_members_list.nim @@ -1,6 +1,6 @@ import NimQml, Tables -import ../../../status/[chat/chat, ens, status, settings] -import ../../../status/types/[setting, status_update] +import status/[chat/chat, ens, status, settings] +import status/types/[setting, status_update] type CommunityMembersRoles {.pure.} = enum diff --git a/src/app/chat/views/community_membership_request_list.nim b/src/app/chat/views/community_membership_request_list.nim index a800ee73e6..bd34b6e051 100644 --- a/src/app/chat/views/community_membership_request_list.nim +++ b/src/app/chat/views/community_membership_request_list.nim @@ -1,7 +1,7 @@ import NimQml, Tables, chronicles -import ../../../status/chat/chat -import ../../../status/status -import ../../../status/accounts +import status/chat/chat +import status/status +import status/accounts import strutils type diff --git a/src/app/chat/views/ens.nim b/src/app/chat/views/ens.nim index 0794cdfa9e..824e6c32f4 100644 --- a/src/app/chat/views/ens.nim +++ b/src/app/chat/views/ens.nim @@ -1,7 +1,7 @@ import NimQml, Tables, json, sequtils, chronicles, times, re, sugar, strutils, os, strformat, algorithm -import ../../../status/[status, contacts] -import ../../../status/ens as status_ens +import status/[status, contacts] +import status/ens as status_ens import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] import ../../../app_service/tasks/marathon/mailserver/worker diff --git a/src/app/chat/views/gif.nim b/src/app/chat/views/gif.nim index dda3b03e47..1a70b91772 100644 --- a/src/app/chat/views/gif.nim +++ b/src/app/chat/views/gif.nim @@ -2,7 +2,7 @@ import # vendor libs NimQml import gif_list -import ../../../status/gif +import status/gif QtObject: diff --git a/src/app/chat/views/gif_list.nim b/src/app/chat/views/gif_list.nim index acf3ea9241..9543b7074b 100644 --- a/src/app/chat/views/gif_list.nim +++ b/src/app/chat/views/gif_list.nim @@ -1,6 +1,6 @@ import NimQml, Tables, sequtils -import ../../../status/gif +import status/gif type GifRoles {.pure.} = enum diff --git a/src/app/chat/views/groups.nim b/src/app/chat/views/groups.nim index 9b288326aa..f8f0fedcd0 100644 --- a/src/app/chat/views/groups.nim +++ b/src/app/chat/views/groups.nim @@ -1,5 +1,5 @@ import NimQml, chronicles, sequtils, json -import ../../../status/status +import status/status import chat_item logScope: diff --git a/src/app/chat/views/message_format.nim b/src/app/chat/views/message_format.nim index 3208df5f2c..24cff438cb 100644 --- a/src/app/chat/views/message_format.nim +++ b/src/app/chat/views/message_format.nim @@ -1,10 +1,10 @@ import NimQml, Tables, json, re -import ../../../status/status -import ../../../status/accounts -import ../../../status/chat -import ../../../status/profile/profile -import ../../../status/ens -import ../../../status/types/[message] +import status/status +import status/accounts +import status/chat +import status/profile/profile +import status/ens +import status/types/[message] import strformat, strutils, sequtils let NEW_LINE = re"\n|\r" diff --git a/src/app/chat/views/message_item.nim b/src/app/chat/views/message_item.nim index 3e648a5e71..02b201379f 100644 --- a/src/app/chat/views/message_item.nim +++ b/src/app/chat/views/message_item.nim @@ -1,7 +1,7 @@ import NimQml, std/wrapnils, chronicles -import ../../../status/status -import ../../../status/chat/stickers -import ../../../status/types/[message] +import status/status +import status/chat/stickers +import status/types/[message] import message_format QtObject: diff --git a/src/app/chat/views/message_list.nim b/src/app/chat/views/message_list.nim index 99317974ce..335ade1630 100644 --- a/src/app/chat/views/message_list.nim +++ b/src/app/chat/views/message_list.nim @@ -1,11 +1,11 @@ import NimQml, Tables, sets, json, sugar, chronicles, sequtils -import ../../../status/status -import ../../../status/accounts -import ../../../status/chat as status_chat -import ../../../status/chat/[stickers,chat] -import ../../../status/profile/profile -import ../../../status/ens -import ../../../status/types/[message] +import status/status +import status/accounts +import status/chat as status_chat +import status/chat/[stickers,chat] +import status/profile/profile +import status/ens +import status/types/[message] import strutils import message_format import user_list diff --git a/src/app/chat/views/message_list_proxy.nim b/src/app/chat/views/message_list_proxy.nim index 81481fccf3..d9cd6a0b6f 100644 --- a/src/app/chat/views/message_list_proxy.nim +++ b/src/app/chat/views/message_list_proxy.nim @@ -1,8 +1,8 @@ import NimQml, strutils import message_list -import ../../../status/[status] -import ../../../status/chat/[message] +import status/[status] +import status/chat/[message] QtObject: type diff --git a/src/app/chat/views/message_search/location_menu_item.nim b/src/app/chat/views/message_search/location_menu_item.nim index f6f34eb454..95f196b881 100644 --- a/src/app/chat/views/message_search/location_menu_item.nim +++ b/src/app/chat/views/message_search/location_menu_item.nim @@ -1,7 +1,7 @@ import json, strformat -import ../../../../status/chat/[chat] -import ../../../../status/[status] +import status/chat/[chat] +import status/[status] import location_menu_sub_model, location_menu_sub_item diff --git a/src/app/chat/views/message_search/location_menu_model.nim b/src/app/chat/views/message_search/location_menu_model.nim index 2d7ae7b6db..395f546189 100644 --- a/src/app/chat/views/message_search/location_menu_model.nim +++ b/src/app/chat/views/message_search/location_menu_model.nim @@ -1,7 +1,7 @@ import NimQml, Tables, strutils -import ../../../../status/chat/[chat] -import ../../../../status/[status] +import status/chat/[chat] +import status/[status] import location_menu_item, location_menu_sub_item, constants diff --git a/src/app/chat/views/message_search/location_menu_sub_model.nim b/src/app/chat/views/message_search/location_menu_sub_model.nim index d902d2909a..c2a40f1bb4 100644 --- a/src/app/chat/views/message_search/location_menu_sub_model.nim +++ b/src/app/chat/views/message_search/location_menu_sub_model.nim @@ -1,7 +1,7 @@ import NimQml, Tables, strutils, strformat -import ../../../../status/chat/[chat] -import ../../../../status/[status] +import status/chat/[chat] +import status/[status] import location_menu_sub_item diff --git a/src/app/chat/views/message_search/view_controller.nim b/src/app/chat/views/message_search/view_controller.nim index 5cbf82488d..dd4b091a0b 100644 --- a/src/app/chat/views/message_search/view_controller.nim +++ b/src/app/chat/views/message_search/view_controller.nim @@ -3,10 +3,10 @@ import NimQml, Tables, json, strutils, chronicles, json_serialization import result_model, result_item, location_menu_model, location_menu_item, location_menu_sub_item import constants as sr_constants -import ../../../../status/[status] -import ../../../../status/chat/[chat] -import ../../../../status/types/[message, setting] -import ../../../../status/libstatus/[settings] +import status/[status] +import status/chat/[chat] +import status/types/[message, setting] +import status/libstatus/[settings] import ../../../../app_service/[main] import ../communities import ../channel diff --git a/src/app/chat/views/messages.nim b/src/app/chat/views/messages.nim index bf45d35fe9..aaedcafc43 100644 --- a/src/app/chat/views/messages.nim +++ b/src/app/chat/views/messages.nim @@ -1,12 +1,12 @@ import NimQml, Tables, json, sequtils, chronicles, times, re, sugar, strutils, os, strformat, algorithm -import ../../../status/[status, contacts, mailservers] -import ../../../status/ens as status_ens -import ../../../status/messages as status_messages -import ../../../status/utils as status_utils -import ../../../status/chat/[chat] -import ../../../status/profile/profile -import ../../../status/types/[message] +import status/[status, contacts, mailservers] +import status/ens as status_ens +import status/messages as status_messages +import status/utils as status_utils +import status/chat/[chat] +import status/profile/profile +import status/types/[message] import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] import ../../../app_service/tasks/marathon/mailserver/worker diff --git a/src/app/chat/views/reactions.nim b/src/app/chat/views/reactions.nim index 2987806b53..fd3f0e9383 100644 --- a/src/app/chat/views/reactions.nim +++ b/src/app/chat/views/reactions.nim @@ -1,8 +1,8 @@ import NimQml, tables, json, chronicles -import ../../../status/[status, chat/chat, settings] +import status/[status, chat/chat, settings] import message_list, chat_item -import ../../../status/utils as status_utils -import ../../../status/types/[message, setting] +import status/utils as status_utils +import status/types/[message, setting] logScope: topics = "reactions-view" diff --git a/src/app/chat/views/sticker_list.nim b/src/app/chat/views/sticker_list.nim index 527d72a769..a1fceaefbe 100644 --- a/src/app/chat/views/sticker_list.nim +++ b/src/app/chat/views/sticker_list.nim @@ -1,6 +1,6 @@ import NimQml, Tables, sequtils -import ../../../status/chat/stickers -import ../../../status/types/[sticker] +import status/chat/stickers +import status/types/[sticker] type StickerRoles {.pure.} = enum diff --git a/src/app/chat/views/sticker_pack_list.nim b/src/app/chat/views/sticker_pack_list.nim index 1e2e1c825a..fa261fff37 100644 --- a/src/app/chat/views/sticker_pack_list.nim +++ b/src/app/chat/views/sticker_pack_list.nim @@ -1,7 +1,7 @@ import NimQml, Tables, sequtils, sugar -import ../../../status/chat/stickers, ./sticker_list -import ../../../status/utils -import ../../../status/types/[sticker] +import status/chat/stickers, ./sticker_list +import status/utils +import status/types/[sticker] type StickerPackRoles {.pure.} = enum diff --git a/src/app/chat/views/stickers.nim b/src/app/chat/views/stickers.nim index 418e16fdb1..45d7cbb478 100644 --- a/src/app/chat/views/stickers.nim +++ b/src/app/chat/views/stickers.nim @@ -5,9 +5,9 @@ import # vendor libs chronicles, NimQml import # status-desktop libs - ../../../status/[status, stickers, wallet, utils], + status/[status, stickers, wallet, utils], sticker_pack_list, sticker_list, chat_item -import ../../../status/types/[sticker, pending_transaction_type] +import status/types/[sticker, pending_transaction_type] import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] import ../../../app_service/tasks/marathon/mailserver/worker diff --git a/src/app/chat/views/transactions.nim b/src/app/chat/views/transactions.nim index c884e0ba74..a3bc95e10d 100644 --- a/src/app/chat/views/transactions.nim +++ b/src/app/chat/views/transactions.nim @@ -1,5 +1,5 @@ import NimQml, chronicles -import ../../../status/status +import status/status logScope: topics = "transactions-view" diff --git a/src/app/chat/views/user_list.nim b/src/app/chat/views/user_list.nim index bdbdb7409d..4e2994ef0e 100644 --- a/src/app/chat/views/user_list.nim +++ b/src/app/chat/views/user_list.nim @@ -1,10 +1,10 @@ import NimQml, Tables, json, chronicles, sequtils -import ../../../status/status -import ../../../status/accounts -import ../../../status/chat as status_chat -import ../../../status/chat/[chat] -import ../../../status/ens -import ../../../status/types/[message] +import status/status +import status/accounts +import status/chat as status_chat +import status/chat/[chat] +import status/ens +import status/types/[message] import strutils diff --git a/src/app/login/core.nim b/src/app/login/core.nim index 2653dceb8c..9b836eb0b3 100644 --- a/src/app/login/core.nim +++ b/src/app/login/core.nim @@ -1,9 +1,9 @@ import NimQml, chronicles, options, std/wrapnils -import ../../status/status -import ../../status/types/[account, rpc_response] -import ../../app_service/signals/[base] +import status/status +import status/types/[account, rpc_response] +import status/signals/[base] import view -import ../../eventemitter +import eventemitter type LoginController* = ref object status*: Status diff --git a/src/app/login/view.nim b/src/app/login/view.nim index 23ad3ac97e..0bba572976 100644 --- a/src/app/login/view.nim +++ b/src/app/login/view.nim @@ -1,9 +1,9 @@ import NimQml, Tables, json, nimcrypto, strformat, json_serialization, chronicles -import ../../status/accounts as AccountModel -import ../../status/types/[account, rpc_response] -import ../../app_service/signals/[base] +import status/accounts as AccountModel +import status/types/[account, rpc_response] +import status/signals/[base] import ../onboarding/views/account_info -import ../../status/status +import status/status type AccountRoles {.pure.} = enum diff --git a/src/app/node/core.nim b/src/app/node/core.nim index 49b0b99693..77a13b78ce 100644 --- a/src/app/node/core.nim +++ b/src/app/node/core.nim @@ -1,8 +1,8 @@ import NimQml, chronicles -import ../../status/[status, node, network] +import status/[status, node, network] import ../../app_service/[main] -import ../../app_service/signals/[base, wallet, discovery_summary, stats] -import ../../eventemitter +import status/signals/[base, wallet, discovery_summary, stats] +import eventemitter import view logScope: diff --git a/src/app/node/view.nim b/src/app/node/view.nim index f78e18eca3..f3586d50a1 100644 --- a/src/app/node/view.nim +++ b/src/app/node/view.nim @@ -1,8 +1,8 @@ import NimQml, chronicles, strutils, json -import ../../status/[status, node, settings, accounts] -import ../../status/types/[setting] +import status/[status, node, settings, accounts] +import status/types/[setting] import ../../app_service/[main] -import ../../app_service/signals/[stats] +import status/signals/[stats] import ../../app_service/tasks/[qt, threadpool] logScope: diff --git a/src/app/onboarding/core.nim b/src/app/onboarding/core.nim index 30ed52afbe..8e84556327 100644 --- a/src/app/onboarding/core.nim +++ b/src/app/onboarding/core.nim @@ -1,9 +1,9 @@ import NimQml, chronicles, std/wrapnils -import ../../status/accounts as AccountModel -import ../../status/status -import ../../status/types/[account] -import ../../app_service/signals/[base] -import ../../eventemitter +import status/accounts as AccountModel +import status/status +import status/types/[account] +import status/signals/[base] +import eventemitter import view type OnboardingController* = ref object diff --git a/src/app/onboarding/view.nim b/src/app/onboarding/view.nim index 008dc809e4..81c3ddbdb6 100644 --- a/src/app/onboarding/view.nim +++ b/src/app/onboarding/view.nim @@ -1,8 +1,8 @@ import NimQml, Tables, json, nimcrypto, strformat, json_serialization, strutils -import ../../status/accounts as AccountModel -import ../../status/[status, wallet] -import ../../status/types/[account, rpc_response] -import ../../app_service/signals/[base] +import status/accounts as AccountModel +import status/[status, wallet] +import status/types/[account, rpc_response] +import status/signals/[base] import views/account_info type diff --git a/src/app/onboarding/views/account_info.nim b/src/app/onboarding/views/account_info.nim index 96c1ca7f32..4e5ec1d428 100644 --- a/src/app/onboarding/views/account_info.nim +++ b/src/app/onboarding/views/account_info.nim @@ -1,5 +1,5 @@ import NimQml -import ../../../status/types/[account] +import status/types/[account] import std/wrapnils QtObject: diff --git a/src/app/profile/core.nim b/src/app/profile/core.nim index 171f97084b..b93372e499 100644 --- a/src/app/profile/core.nim +++ b/src/app/profile/core.nim @@ -1,17 +1,17 @@ import NimQml, json, strutils, sugar, sequtils, tables import json_serialization -import ../../status/profile/[profile, mailserver] -import ../../status/[status, settings] -import ../../status/contacts as status_contacts -import ../../status/chat as status_chat -import ../../status/devices as status_devices -import ../../status/chat/chat -import ../../status/wallet -import ../../status/types/[account, transaction, setting] +import status/profile/[profile, mailserver] +import status/[status, settings] +import status/contacts as status_contacts +import status/chat as status_chat +import status/devices as status_devices +import status/chat/chat +import status/wallet +import status/types/[account, transaction, setting] import ../../app_service/[main] -import ../../app_service/signals/[base, messages] +import status/signals/[base, messages] import ../../app_service/tasks/marathon/mailserver/events -import ../../eventemitter +import eventemitter import view import views/[ens_manager, devices, network, mailservers, contacts, muted_chats] import ../chat/views/channels_list diff --git a/src/app/profile/view.nim b/src/app/profile/view.nim index 457ac0a5a3..4fa8dabc85 100644 --- a/src/app/profile/view.nim +++ b/src/app/profile/view.nim @@ -2,16 +2,16 @@ import NimQml, sequtils, strutils, sugar, os, json, chronicles import views/[mailservers_list, ens_manager, contacts, devices, mailservers, mnemonic, network, fleets, profile_info, device_list, dapp_list, profile_picture, profile_settings, muted_chats] import chronicles import ../chat/views/channels_list -import ../../status/libstatus/accounts as status_accounts -import ../../status/profile/profile -import ../../status/profile as status_profile -import ../../status/contacts as status_contacts -import ../../status/status -import ../../status/ens as status_ens -import ../../status/chat/chat -import ../../status/types/[setting, os_notification] -import ../../status/constants as accountConstants -import ../../status/notifications/[os_notifications] +import status/libstatus/accounts as status_accounts +import status/profile/profile +import status/profile as status_profile +import status/contacts as status_contacts +import status/status +import status/ens as status_ens +import status/chat/chat +import status/types/[setting, os_notification] +import status/constants as accountConstants +import status/notifications/[os_notifications] import ../../app_service/[main] import qrcode/qrcode import ../utils/image_utils diff --git a/src/app/profile/views/contact_list.nim b/src/app/profile/views/contact_list.nim index 81b144480a..23f17af29e 100644 --- a/src/app/profile/views/contact_list.nim +++ b/src/app/profile/views/contact_list.nim @@ -1,7 +1,7 @@ import NimQml, chronicles import Tables -import ../../../status/profile/profile -from ../../../status/ens import nil +import status/profile/profile +from status/ens import nil type ContactRoles {.pure.} = enum diff --git a/src/app/profile/views/contacts.nim b/src/app/profile/views/contacts.nim index 1e03e28fc6..63ad3c8e7e 100644 --- a/src/app/profile/views/contacts.nim +++ b/src/app/profile/views/contacts.nim @@ -1,10 +1,10 @@ import NimQml, chronicles, sequtils, sugar, strutils, json -import ../../../status/utils as status_utils -import ../../../status/status -import ../../../status/chat/chat +import status/utils as status_utils +import status/status +import status/chat/chat import contact_list -import ../../../status/profile/profile -import ../../../status/ens as status_ens +import status/profile/profile +import status/ens as status_ens import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/profile/views/custom_networks.nim b/src/app/profile/views/custom_networks.nim index 0472d17221..8973572609 100644 --- a/src/app/profile/views/custom_networks.nim +++ b/src/app/profile/views/custom_networks.nim @@ -1,9 +1,9 @@ import NimQml import Tables import json, sequtils -import ../../../status/settings -import ../../../status/types/[setting] -import ../../../status/status +import status/settings +import status/types/[setting] +import status/status type CustomNetworkRoles {.pure.} = enum diff --git a/src/app/profile/views/dapp_list.nim b/src/app/profile/views/dapp_list.nim index 2042f65491..d9fcc65f3e 100644 --- a/src/app/profile/views/dapp_list.nim +++ b/src/app/profile/views/dapp_list.nim @@ -1,6 +1,6 @@ import NimQml import Tables -import ../../../status/status +import status/status import permission_list type diff --git a/src/app/profile/views/device_list.nim b/src/app/profile/views/device_list.nim index 137c16dae0..ce04c03223 100644 --- a/src/app/profile/views/device_list.nim +++ b/src/app/profile/views/device_list.nim @@ -1,6 +1,6 @@ import NimQml import Tables -import ../../../status/types/[installation] +import status/types/[installation] type DeviceRoles {.pure.} = enum diff --git a/src/app/profile/views/devices.nim b/src/app/profile/views/devices.nim index 40aea3fdac..fe8cc45213 100644 --- a/src/app/profile/views/devices.nim +++ b/src/app/profile/views/devices.nim @@ -1,7 +1,7 @@ import NimQml, chronicles -import ../../../status/status -import ../../../status/devices as status_devices -import ../../../status/types/[installation] +import status/status +import status/devices as status_devices +import status/types/[installation] import device_list logScope: diff --git a/src/app/profile/views/ens_manager.nim b/src/app/profile/views/ens_manager.nim index ee12c21844..f61457fd8b 100644 --- a/src/app/profile/views/ens_manager.nim +++ b/src/app/profile/views/ens_manager.nim @@ -3,11 +3,11 @@ import Tables import json import sequtils import strutils -import ../../../status/ens as status_ens -import ../../../status/utils as status_utils -import ../../../status/[status, settings, wallet] -import ../../../status/wallet -import ../../../status/types/[setting, transaction, rpc_response] +import status/ens as status_ens +import status/utils as status_utils +import status/[status, settings, wallet] +import status/wallet +import status/types/[setting, transaction, rpc_response] import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] import sets diff --git a/src/app/profile/views/fleets.nim b/src/app/profile/views/fleets.nim index fc827366cb..ba192e3448 100644 --- a/src/app/profile/views/fleets.nim +++ b/src/app/profile/views/fleets.nim @@ -1,6 +1,6 @@ import NimQml, json import chronicles, strutils -import ../../../status/[status, settings, accounts] +import status/[status, settings, accounts] QtObject: type Fleets * = ref object of QObject diff --git a/src/app/profile/views/mailservers.nim b/src/app/profile/views/mailservers.nim index 401ddcbc30..89753c303c 100644 --- a/src/app/profile/views/mailservers.nim +++ b/src/app/profile/views/mailservers.nim @@ -1,6 +1,6 @@ import NimQml, chronicles -import ../../../status/[status, settings] -import ../../../status/profile/mailserver +import status/[status, settings] +import status/profile/mailserver import mailservers_list import ../../../app_service/[main] import ../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/profile/views/mailservers_list.nim b/src/app/profile/views/mailservers_list.nim index 1c355e1de0..402eb14077 100644 --- a/src/app/profile/views/mailservers_list.nim +++ b/src/app/profile/views/mailservers_list.nim @@ -1,6 +1,6 @@ import NimQml import Tables -import ../../../status/profile/mailserver +import status/profile/mailserver type MailServerRoles {.pure.} = enum diff --git a/src/app/profile/views/mnemonic.nim b/src/app/profile/views/mnemonic.nim index 1739861269..128104c2f7 100644 --- a/src/app/profile/views/mnemonic.nim +++ b/src/app/profile/views/mnemonic.nim @@ -1,6 +1,6 @@ import NimQml, chronicles, strutils -import ../../../status/[status, settings] -import ../../../status/types/[setting] +import status/[status, settings] +import status/types/[setting] import options logScope: diff --git a/src/app/profile/views/muted_chats.nim b/src/app/profile/views/muted_chats.nim index c9b09fb9e0..ec81de14ef 100644 --- a/src/app/profile/views/muted_chats.nim +++ b/src/app/profile/views/muted_chats.nim @@ -1,10 +1,10 @@ import NimQml, sequtils, strutils, json, chronicles import chronicles import ../../chat/views/channels_list -import ../../../status/profile as status_profile -import ../../../status/contacts as status_contacts -import ../../../status/status -import ../../../status/chat/chat +import status/profile as status_profile +import status/contacts as status_contacts +import status/status +import status/chat/chat logScope: topics = "muted-chats-view" diff --git a/src/app/profile/views/network.nim b/src/app/profile/views/network.nim index 0b5d15306b..65b85fd0a8 100644 --- a/src/app/profile/views/network.nim +++ b/src/app/profile/views/network.nim @@ -1,6 +1,6 @@ import NimQml, chronicles -import ../../../status/status -import ../../../status/network +import status/status +import status/network import custom_networks logScope: diff --git a/src/app/profile/views/permission_list.nim b/src/app/profile/views/permission_list.nim index 62d8b8b2fe..06db591afc 100644 --- a/src/app/profile/views/permission_list.nim +++ b/src/app/profile/views/permission_list.nim @@ -1,6 +1,6 @@ import NimQml import Tables -import ../../../status/status +import status/status import sets import sequtils diff --git a/src/app/profile/views/profile_info.nim b/src/app/profile/views/profile_info.nim index 05bf2055fb..7fd8776ee1 100644 --- a/src/app/profile/views/profile_info.nim +++ b/src/app/profile/views/profile_info.nim @@ -1,6 +1,6 @@ import NimQml import chronicles -import ../../../status/profile/profile +import status/profile/profile import std/wrapnils QtObject: diff --git a/src/app/profile/views/profile_picture.nim b/src/app/profile/views/profile_picture.nim index 8a3927ee76..c12ddd2023 100644 --- a/src/app/profile/views/profile_picture.nim +++ b/src/app/profile/views/profile_picture.nim @@ -2,8 +2,8 @@ import NimQml import chronicles import profile_info import ../../utils/image_utils -import ../../../status/profile as status_profile -import ../../../status/status +import status/profile as status_profile +import status/status logScope: diff --git a/src/app/profile/views/profile_settings.nim b/src/app/profile/views/profile_settings.nim index a944250e4b..87cfe4024d 100644 --- a/src/app/profile/views/profile_settings.nim +++ b/src/app/profile/views/profile_settings.nim @@ -1,8 +1,8 @@ import NimQml, os import chronicles import profile_info -import ../../../status/status -import ../../../status/constants as accountConstants +import status/status +import status/constants as accountConstants logScope: topics = "profile-settings-view" diff --git a/src/app/provider/core.nim b/src/app/provider/core.nim index 98d76e17ef..62173668b3 100644 --- a/src/app/provider/core.nim +++ b/src/app/provider/core.nim @@ -1,5 +1,5 @@ import NimQml, chronicles -import ../../status/status +import status/status import view logScope: diff --git a/src/app/provider/view.nim b/src/app/provider/view.nim index 9ee208b8f9..788c443616 100644 --- a/src/app/provider/view.nim +++ b/src/app/provider/view.nim @@ -1,6 +1,6 @@ import NimQml -import ../../status/[status, ens, chat/stickers, wallet, settings, provider] -import ../../status/types/[setting] +import status/[status, ens, chat/stickers, wallet, settings, provider] +import status/types/[setting] import json, json_serialization, sets, strutils import chronicles import nbaser diff --git a/src/app/utilsView/core.nim b/src/app/utilsView/core.nim index 114e85c0b4..7f7e64be46 100644 --- a/src/app/utilsView/core.nim +++ b/src/app/utilsView/core.nim @@ -1,8 +1,8 @@ import NimQml, chronicles -import ../../status/[status, node, network] +import status/[status, node, network] import ../../app_service/[main] import view -import ../../eventemitter +import eventemitter logScope: topics = "utils" diff --git a/src/app/utilsView/view.nim b/src/app/utilsView/view.nim index 855ac7fe5e..155a2cf068 100644 --- a/src/app/utilsView/view.nim +++ b/src/app/utilsView/view.nim @@ -1,11 +1,11 @@ import NimQml, os, strformat, strutils, parseUtils, chronicles import stint -import ../../status/[status, wallet, settings, updates] -import ../../status/stickers -import ../../status/tokens as status_tokens -import ../../status/utils as status_utils -import ../../status/ens as status_ens -import ../../status/types/[network] +import status/[status, wallet, settings, updates] +import status/stickers +import status/tokens as status_tokens +import status/utils as status_utils +import status/ens as status_ens +import status/types/[network] import ../../app_service/[main] import ../../app_service/tasks/[qt, threadpool] import ../utils/image_utils diff --git a/src/app/wallet/v1/core.nim b/src/app/wallet/v1/core.nim index d470cf2071..07f2cc7575 100644 --- a/src/app/wallet/v1/core.nim +++ b/src/app/wallet/v1/core.nim @@ -3,13 +3,13 @@ import NimQml, strformat, strutils, chronicles, sugar, sequtils import view import views/[asset_list, account_list, account_item] -import ../../../status/[status, wallet, settings] -import ../../../status/wallet/account as WalletTypes -import ../../../status/types/[transaction, setting] +import status/[status, wallet, settings] +import status/wallet/account as WalletTypes +import status/types/[transaction, setting] import ../../../app_service/[main] -import ../../../app_service/signals/[base] -import ../../../app_service/signals/wallet as wallet_signal -import ../../../eventemitter +import status/signals/[base] +import status/signals/wallet as wallet_signal +import eventemitter logScope: topics = "wallet-core" diff --git a/src/app/wallet/v1/view.nim b/src/app/wallet/v1/view.nim index 6b11b18def..b1fe6154f5 100644 --- a/src/app/wallet/v1/view.nim +++ b/src/app/wallet/v1/view.nim @@ -2,7 +2,7 @@ import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, t import NimQml, chronicles, stint import - ../../../status/[status, wallet], + status/[status, wallet], views/[accounts, collectibles, transactions, tokens, gas, ens, dapp_browser, history, balance, utils, asset_list, account_list] import ../../../app_service/[main] diff --git a/src/app/wallet/v1/views/account_item.nim b/src/app/wallet/v1/views/account_item.nim index df8ec3df73..2f9fd35004 100644 --- a/src/app/wallet/v1/views/account_item.nim +++ b/src/app/wallet/v1/views/account_item.nim @@ -1,5 +1,5 @@ import NimQml, std/wrapnils, strformat, options -from ../../../../status/wallet import WalletAccount +from status/wallet import WalletAccount import ./asset_list QtObject: diff --git a/src/app/wallet/v1/views/account_list.nim b/src/app/wallet/v1/views/account_list.nim index c77a38d493..acbef0dcc5 100644 --- a/src/app/wallet/v1/views/account_list.nim +++ b/src/app/wallet/v1/views/account_list.nim @@ -1,7 +1,7 @@ import NimQml, Tables, random, strformat, strutils, json_serialization import sequtils as sequtils import account_item, asset_list -from ../../../../status/wallet import WalletAccount, Asset, CollectibleList +from status/wallet import WalletAccount, Asset, CollectibleList const accountColors* = ["#9B832F", "#D37EF4", "#1D806F", "#FA6565", "#7CDA00", "#887af9", "#8B3131"] type diff --git a/src/app/wallet/v1/views/accounts.nim b/src/app/wallet/v1/views/accounts.nim index dd0b758a9b..942d006fc4 100644 --- a/src/app/wallet/v1/views/accounts.nim +++ b/src/app/wallet/v1/views/accounts.nim @@ -1,10 +1,10 @@ import NimQml, json, sequtils, chronicles, strutils, strformat, json import - ../../../../status/[status, settings], - ../../../../status/wallet as status_wallet, - ../../../../status/types/[rpc_response], - ../../../../app_service/signals/[base] + status/[status, settings], + status/wallet as status_wallet, + status/types/[rpc_response], + status/signals/[base] import account_list, account_item diff --git a/src/app/wallet/v1/views/asset_list.nim b/src/app/wallet/v1/views/asset_list.nim index bf37aeb6e8..e739908ac8 100644 --- a/src/app/wallet/v1/views/asset_list.nim +++ b/src/app/wallet/v1/views/asset_list.nim @@ -1,5 +1,5 @@ import NimQml, tables -from ../../../../status/wallet import Asset +from status/wallet import Asset type AssetRoles {.pure.} = enum diff --git a/src/app/wallet/v1/views/balance.nim b/src/app/wallet/v1/views/balance.nim index ca961d2af1..ec88dd1470 100644 --- a/src/app/wallet/v1/views/balance.nim +++ b/src/app/wallet/v1/views/balance.nim @@ -2,8 +2,8 @@ import atomics, strutils, sequtils, json, tables, chronicles, web3/[ethtypes, co import NimQml, json, sequtils, chronicles, strutils, strformat, json import - ../../../../status/[status, wallet, tokens], - ../../../../status/tokens as status_tokens + status/[status, wallet, tokens], + status/tokens as status_tokens import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/wallet/v1/views/collectibles.nim b/src/app/wallet/v1/views/collectibles.nim index f71ca494c5..5331352ef5 100644 --- a/src/app/wallet/v1/views/collectibles.nim +++ b/src/app/wallet/v1/views/collectibles.nim @@ -2,8 +2,8 @@ import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, t import NimQml, json, sequtils, chronicles, strutils, strformat, json import - ../../../../status/[status, settings, wallet, tokens, utils], - ../../../../status/wallet/collectibles as status_collectibles + status/[status, settings, wallet, tokens, utils], + status/wallet/collectibles as status_collectibles import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/wallet/v1/views/collectibles_list.nim b/src/app/wallet/v1/views/collectibles_list.nim index ce00972e95..0c1547970d 100644 --- a/src/app/wallet/v1/views/collectibles_list.nim +++ b/src/app/wallet/v1/views/collectibles_list.nim @@ -1,5 +1,5 @@ import NimQml, tables -from ../../../../status/wallet import CollectibleList +from status/wallet import CollectibleList type CollectiblesRoles {.pure.} = enum diff --git a/src/app/wallet/v1/views/dapp_browser.nim b/src/app/wallet/v1/views/dapp_browser.nim index 058c3da67f..0cdbee0605 100644 --- a/src/app/wallet/v1/views/dapp_browser.nim +++ b/src/app/wallet/v1/views/dapp_browser.nim @@ -1,8 +1,8 @@ import sequtils, json, chronicles, web3/[ethtypes, conversions], stint import NimQml, json, sequtils, chronicles, strutils, json -import ../../../../status/[status, settings, wallet] -import ../../../../status/types/[setting] +import status/[status, settings, wallet] +import status/types/[setting] import account_list, account_item, accounts diff --git a/src/app/wallet/v1/views/ens.nim b/src/app/wallet/v1/views/ens.nim index b2432c9f0a..20d2abe775 100644 --- a/src/app/wallet/v1/views/ens.nim +++ b/src/app/wallet/v1/views/ens.nim @@ -2,8 +2,8 @@ import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, t import NimQml, json, sequtils, chronicles, strutils, strformat, json import - ../../../../status/[status, settings, wallet, tokens], - ../../../../status/ens as status_ens + status/[status, settings, wallet, tokens], + status/ens as status_ens import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/wallet/v1/views/gas.nim b/src/app/wallet/v1/views/gas.nim index 9b77a93023..05bfd0a43e 100644 --- a/src/app/wallet/v1/views/gas.nim +++ b/src/app/wallet/v1/views/gas.nim @@ -2,8 +2,8 @@ import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, c import NimQml, json, sequtils, chronicles, strutils, strformat, json import - ../../../../status/[status, wallet, utils], - ../../../../status/types/[gas_prediction] + status/[status, wallet, utils], + status/types/[gas_prediction] import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/wallet/v1/views/history.nim b/src/app/wallet/v1/views/history.nim index 03d788dc38..585e45dfd8 100644 --- a/src/app/wallet/v1/views/history.nim +++ b/src/app/wallet/v1/views/history.nim @@ -3,9 +3,9 @@ from sugar import `=>`, `->` import NimQml, json, sequtils, chronicles, strutils, json import - ../../../../status/[status, wallet, utils], - ../../../../status/wallet as status_wallet, - ../../../../status/types/[transaction] + status/[status, wallet, utils], + status/wallet as status_wallet, + status/types/[transaction] import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] import account_list, account_item, transaction_list, accounts, transactions diff --git a/src/app/wallet/v1/views/token_list.nim b/src/app/wallet/v1/views/token_list.nim index 1b82c6185f..64d9dddb36 100644 --- a/src/app/wallet/v1/views/token_list.nim +++ b/src/app/wallet/v1/views/token_list.nim @@ -5,8 +5,8 @@ import # vendor libs NimQml import # status-desktop libs - ../../../../status/[utils, tokens, settings], - ../../../../status/status + status/[utils, tokens, settings], + status/status import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] import ../../../../app_service/tasks/marathon/mailserver/worker diff --git a/src/app/wallet/v1/views/tokens.nim b/src/app/wallet/v1/views/tokens.nim index f435b10fe7..4d9baf8488 100644 --- a/src/app/wallet/v1/views/tokens.nim +++ b/src/app/wallet/v1/views/tokens.nim @@ -1,7 +1,7 @@ import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, tables, chronicles, web3/[ethtypes, conversions], stint import NimQml, json, sequtils, chronicles, strutils, strformat, json -import ../../../../status/[status, settings, wallet, tokens, utils] +import status/[status, settings, wallet, tokens, utils] import ../../../../app_service/[main] import account_list, account_item, transaction_list, accounts, asset_list, token_list diff --git a/src/app/wallet/v1/views/transaction_list.nim b/src/app/wallet/v1/views/transaction_list.nim index 9d90bcbdee..4774544c89 100644 --- a/src/app/wallet/v1/views/transaction_list.nim +++ b/src/app/wallet/v1/views/transaction_list.nim @@ -1,5 +1,5 @@ import NimQml, tables -from ../../../../status/wallet import Transaction +from status/wallet import Transaction type TransactionRoles {.pure.} = enum diff --git a/src/app/wallet/v1/views/transactions.nim b/src/app/wallet/v1/views/transactions.nim index 6de8a72aea..8053d0e984 100644 --- a/src/app/wallet/v1/views/transactions.nim +++ b/src/app/wallet/v1/views/transactions.nim @@ -2,8 +2,8 @@ import algorithm, atomics, sequtils, strformat, strutils, sugar, sequtils, json, import NimQml, json, sequtils, chronicles, strutils, strformat, json, stint import - ../../../../status/[status, settings, wallet, tokens, utils], - ../../../../status/wallet as status_wallet + status/[status, settings, wallet, tokens, utils], + status/wallet as status_wallet import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/wallet/v2/core.nim b/src/app/wallet/v2/core.nim index 358df552ed..084f416814 100644 --- a/src/app/wallet/v2/core.nim +++ b/src/app/wallet/v2/core.nim @@ -3,13 +3,13 @@ import NimQml, strformat, strutils, chronicles, sugar, sequtils import view import views/[account_list, account_item] -import ../../../status/[status, wallet2, settings] -import ../../../status/wallet2/account as WalletTypes -import ../../../status/types/[transaction, setting] +import status/[status, wallet2, settings] +import status/wallet2/account as WalletTypes +import status/types/[transaction, setting] import ../../../app_service/[main] -import ../../../app_service/signals/[base] -import ../../../app_service/signals/wallet as wallet_signal -import ../../../eventemitter +import status/signals/[base] +import status/signals/wallet as wallet_signal +import eventemitter logScope: topics = "app-wallet2" diff --git a/src/app/wallet/v2/view.nim b/src/app/wallet/v2/view.nim index 5f3d9505b0..40dd2a5ad7 100644 --- a/src/app/wallet/v2/view.nim +++ b/src/app/wallet/v2/view.nim @@ -1,7 +1,7 @@ import atomics, strformat, strutils, sequtils, json, std/wrapnils, parseUtils, tables import NimQml, chronicles, stint -import ../../../status/[status, wallet2] +import status/[status, wallet2] import views/[accounts, account_list, collectibles] import views/buy_sell_crypto/[service_controller] import ../../../app_service/[main] diff --git a/src/app/wallet/v2/views/account_item.nim b/src/app/wallet/v2/views/account_item.nim index 64f948627e..fed2f40eda 100644 --- a/src/app/wallet/v2/views/account_item.nim +++ b/src/app/wallet/v2/views/account_item.nim @@ -1,5 +1,5 @@ import NimQml, std/wrapnils, strformat, options -from ../../../../status/wallet2 import WalletAccount +from status/wallet2 import WalletAccount QtObject: type AccountItemView* = ref object of QObject diff --git a/src/app/wallet/v2/views/account_list.nim b/src/app/wallet/v2/views/account_list.nim index 15880cc411..94ad7ce4ce 100644 --- a/src/app/wallet/v2/views/account_list.nim +++ b/src/app/wallet/v2/views/account_list.nim @@ -1,7 +1,7 @@ import NimQml, Tables, random, strformat, strutils, json_serialization import sequtils as sequtils import account_item -from ../../../../status/wallet2 import WalletAccount, Asset, CollectibleList +from status/wallet2 import WalletAccount, Asset, CollectibleList const accountColors* = ["#9B832F", "#D37EF4", "#1D806F", "#FA6565", "#7CDA00", "#887af9", "#8B3131"] diff --git a/src/app/wallet/v2/views/accounts.nim b/src/app/wallet/v2/views/accounts.nim index 236a3e1f21..f1cf7080dd 100644 --- a/src/app/wallet/v2/views/accounts.nim +++ b/src/app/wallet/v2/views/accounts.nim @@ -1,10 +1,10 @@ import NimQml, json, sequtils, chronicles, strutils, strformat, json import - ../../../../status/[status, settings], - ../../../../status/wallet2 as status_wallet, - ../../../../status/types/[rpc_response], - ../../../../app_service/signals/[base] + status/[status, settings], + status/wallet2 as status_wallet, + status/types/[rpc_response], + status/signals/[base] import account_list, account_item diff --git a/src/app/wallet/v2/views/asset_list.nim b/src/app/wallet/v2/views/asset_list.nim index fb0e82a0d3..f77410c21d 100644 --- a/src/app/wallet/v2/views/asset_list.nim +++ b/src/app/wallet/v2/views/asset_list.nim @@ -1,5 +1,5 @@ import NimQml, Tables -from ../../../../status/wallet2 import OpenseaAsset +from status/wallet2 import OpenseaAsset type AssetRoles {.pure.} = enum diff --git a/src/app/wallet/v2/views/buy_sell_crypto/service_controller.nim b/src/app/wallet/v2/views/buy_sell_crypto/service_controller.nim index 5c2acb7203..c9fb462035 100644 --- a/src/app/wallet/v2/views/buy_sell_crypto/service_controller.nim +++ b/src/app/wallet/v2/views/buy_sell_crypto/service_controller.nim @@ -3,7 +3,7 @@ import NimQml, json, strutils, chronicles import service_model, service_item import ../../../../../app_service/[main] -import ../../../../../status/[status, wallet2] +import status/[status, wallet2] logScope: topics = "app-wallet2-crypto-service" diff --git a/src/app/wallet/v2/views/buy_sell_crypto/service_item.nim b/src/app/wallet/v2/views/buy_sell_crypto/service_item.nim index 184ee01829..571d61d795 100644 --- a/src/app/wallet/v2/views/buy_sell_crypto/service_item.nim +++ b/src/app/wallet/v2/views/buy_sell_crypto/service_item.nim @@ -1,6 +1,6 @@ import json, strformat, chronicles -include ../../../../../status/utils/[json_utils] +include status/utils/[json_utils] logScope: topics = "app-wallet2-crypto-service" diff --git a/src/app/wallet/v2/views/collectibles.nim b/src/app/wallet/v2/views/collectibles.nim index 87032fcb8b..6d891a0cae 100644 --- a/src/app/wallet/v2/views/collectibles.nim +++ b/src/app/wallet/v2/views/collectibles.nim @@ -1,6 +1,6 @@ import NimQml, Tables, json, chronicles -import ../../../../status/[status, wallet2] +import status/[status, wallet2] import ../../../../app_service/[main] import ../../../../app_service/tasks/[qt, threadpool] diff --git a/src/app/wallet/v2/views/collection_list.nim b/src/app/wallet/v2/views/collection_list.nim index 789d719c7d..d24e0abeeb 100644 --- a/src/app/wallet/v2/views/collection_list.nim +++ b/src/app/wallet/v2/views/collection_list.nim @@ -1,5 +1,5 @@ import NimQml, Tables -from ../../../../status/wallet2 import OpenseaCollection +from status/wallet2 import OpenseaCollection type CollectionRoles {.pure.} = enum diff --git a/src/app_service/async_service/chat/async_tasks.nim b/src/app_service/async_service/chat/async_tasks.nim index 6ee64a5760..3175790dc9 100644 --- a/src/app_service/async_service/chat/async_tasks.nim +++ b/src/app_service/async_service/chat/async_tasks.nim @@ -1,4 +1,4 @@ -include ../../../status/utils/json_utils +include status/utils/json_utils type AsyncSearchMessagesTaskArg = ref object of QObjectTaskArg diff --git a/src/app_service/async_service/chat/service.nim b/src/app_service/async_service/chat/service.nim index a6d3de85de..0c4131af15 100644 --- a/src/app_service/async_service/chat/service.nim +++ b/src/app_service/async_service/chat/service.nim @@ -2,10 +2,10 @@ import NimQml import json, chronicles import ../../tasks/[qt, threadpool] -import ../../../status/status -import ../../../status/libstatus/chat as status_chat +import status/status +import status/libstatus/chat as status_chat -include ../../../status/chat/utils +include status/chat/utils include async_tasks logScope: diff --git a/src/app_service/async_service/wallet/async_tasks.nim b/src/app_service/async_service/wallet/async_tasks.nim index 843c2d8f8d..f515d5a0a5 100644 --- a/src/app_service/async_service/wallet/async_tasks.nim +++ b/src/app_service/async_service/wallet/async_tasks.nim @@ -1,4 +1,4 @@ -include ../../../status/utils/json_utils +include status/utils/json_utils ################################################# # Async request for the list of services to buy/sell crypto diff --git a/src/app_service/async_service/wallet/service.nim b/src/app_service/async_service/wallet/service.nim index 4613601f84..d83881aca3 100644 --- a/src/app_service/async_service/wallet/service.nim +++ b/src/app_service/async_service/wallet/service.nim @@ -2,8 +2,8 @@ import NimQml import json, chronicles import ../../tasks/[qt, threadpool] -import ../../../status/[status, wallet2] -import ../../../status/libstatus/wallet as status_wallet +import status/[status, wallet2] +import status/libstatus/wallet as status_wallet include async_tasks diff --git a/src/app_service/main.nim b/src/app_service/main.nim index 1821cd9792..ad60cc5e4b 100644 --- a/src/app_service/main.nim +++ b/src/app_service/main.nim @@ -1,5 +1,5 @@ import chronicles, task_runner -import ../status/status +import status/status import ./tasks/marathon, ./tasks/marathon/worker, diff --git a/src/app_service/service/os_notification/service.nim b/src/app_service/service/os_notification/service.nim index 75c9100c2e..92c5c2017b 100644 --- a/src/app_service/service/os_notification/service.nim +++ b/src/app_service/service/os_notification/service.nim @@ -1,8 +1,8 @@ import NimQml, json, chronicles -import ../../../status/[status] -import ../../../status/notifications/[os_notifications] -import ../../../status/types/[os_notification] +import status/[status] +import status/notifications/[os_notifications] +import status/types/[os_notification] logScope: topics = "os-notification-service" diff --git a/src/app_service/signals/base.nim b/src/app_service/signals/base.nim deleted file mode 100644 index f2a7ec7851..0000000000 --- a/src/app_service/signals/base.nim +++ /dev/null @@ -1,15 +0,0 @@ -import json_serialization -import signal_type - -import ../../eventemitter - -export signal_type - -type Signal* = ref object of Args - signalType* {.serializedFieldName("type").}: SignalType - -type StatusGoError* = object - error*: string - -type NodeSignal* = ref object of Signal - event*: StatusGoError \ No newline at end of file diff --git a/src/app_service/signals/community.nim b/src/app_service/signals/community.nim deleted file mode 100644 index cfb318a84c..0000000000 --- a/src/app_service/signals/community.nim +++ /dev/null @@ -1,13 +0,0 @@ -import json - -import base - -import ../../status/types/community - -type CommunitySignal* = ref object of Signal - community*: Community - -proc fromEvent*(event: JsonNode): Signal = - var signal: CommunitySignal = CommunitySignal() - signal.community = event["event"].toCommunity() - result = signal \ No newline at end of file diff --git a/src/app_service/signals/discovery_summary.nim b/src/app_service/signals/discovery_summary.nim deleted file mode 100644 index e52187f838..0000000000 --- a/src/app_service/signals/discovery_summary.nim +++ /dev/null @@ -1,13 +0,0 @@ -import json - -import base - -type DiscoverySummarySignal* = ref object of Signal - enodes*: seq[string] - -proc fromEvent*(jsonSignal: JsonNode): Signal = - var signal:DiscoverySummarySignal = DiscoverySummarySignal() - if jsonSignal["event"].kind != JNull: - for discoveryItem in jsonSignal["event"]: - signal.enodes.add(discoveryItem["enode"].getStr) - result = signal \ No newline at end of file diff --git a/src/app_service/signals/envelope.nim b/src/app_service/signals/envelope.nim deleted file mode 100644 index 0dbfa901f7..0000000000 --- a/src/app_service/signals/envelope.nim +++ /dev/null @@ -1,14 +0,0 @@ -import json - -import base - -type EnvelopeSentSignal* = ref object of Signal - messageIds*: seq[string] - -proc fromEvent*(jsonSignal: JsonNode): Signal = - var signal:EnvelopeSentSignal = EnvelopeSentSignal() - if jsonSignal["event"].kind != JNull and jsonSignal["event"].hasKey("ids") and jsonSignal["event"]["ids"].kind != JNull: - for messageId in jsonSignal["event"]["ids"]: - signal.messageIds.add(messageId.getStr) - result = signal - \ No newline at end of file diff --git a/src/app_service/signals/expired.nim b/src/app_service/signals/expired.nim deleted file mode 100644 index e30a5a4f41..0000000000 --- a/src/app_service/signals/expired.nim +++ /dev/null @@ -1,14 +0,0 @@ -import json - -import base - -type EnvelopeExpiredSignal* = ref object of Signal - messageIds*: seq[string] - -proc fromEvent*(jsonSignal: JsonNode): Signal = - var signal:EnvelopeExpiredSignal = EnvelopeExpiredSignal() - if jsonSignal["event"].kind != JNull and jsonSignal["event"].hasKey("ids") and jsonSignal["event"]["ids"].kind != JNull: - for messageId in jsonSignal["event"]["ids"]: - signal.messageIds.add(messageId.getStr) - result = signal - \ No newline at end of file diff --git a/src/app_service/signals/mailserver.nim b/src/app_service/signals/mailserver.nim deleted file mode 100644 index e6546fbc2f..0000000000 --- a/src/app_service/signals/mailserver.nim +++ /dev/null @@ -1,29 +0,0 @@ -import json - -import base - -type MailserverRequestCompletedSignal* = ref object of Signal - requestID*: string - lastEnvelopeHash*: string - cursor*: string - errorMessage*: string - error*: bool - -type MailserverRequestExpiredSignal* = ref object of Signal - # TODO - -proc fromCompletedEvent*(jsonSignal: JsonNode): Signal = - var signal:MailserverRequestCompletedSignal = MailserverRequestCompletedSignal() - if jsonSignal["event"].kind != JNull: - signal.requestID = jsonSignal["event"]{"requestID"}.getStr() - signal.lastEnvelopeHash = jsonSignal["event"]{"lastEnvelopeHash"}.getStr() - signal.cursor = jsonSignal["event"]{"cursor"}.getStr() - signal.errorMessage = jsonSignal["event"]{"errorMessage"}.getStr() - signal.error = signal.errorMessage != "" - result = signal - -proc fromExpiredEvent*(jsonSignal: JsonNode): Signal = - var signal:MailserverRequestExpiredSignal = MailserverRequestExpiredSignal() - # TODO: parse signal - result = signal - \ No newline at end of file diff --git a/src/app_service/signals/messages.nim b/src/app_service/signals/messages.nim deleted file mode 100644 index f19c3038d7..0000000000 --- a/src/app_service/signals/messages.nim +++ /dev/null @@ -1,95 +0,0 @@ -import json, chronicles - -import base - -import ../../status/types/[message, chat, community, profile, installation, - activity_center_notification, status_update, removed_message] - -type MessageSignal* = ref object of Signal - messages*: seq[Message] - pinnedMessages*: seq[Message] - chats*: seq[Chat] - contacts*: seq[Profile] - installations*: seq[Installation] - emojiReactions*: seq[Reaction] - communities*: seq[Community] - membershipRequests*: seq[CommunityMembershipRequest] - activityCenterNotification*: seq[ActivityCenterNotification] - statusUpdates*: seq[StatusUpdate] - deletedMessages*: seq[RemovedMessage] - -proc fromEvent*(event: JsonNode): Signal = - var signal:MessageSignal = MessageSignal() - signal.messages = @[] - signal.contacts = @[] - - if event["event"]{"contacts"} != nil: - for jsonContact in event["event"]["contacts"]: - signal.contacts.add(jsonContact.toProfileModel()) - - var chatsWithMentions: seq[string] = @[] - - if event["event"]{"messages"} != nil: - for jsonMsg in event["event"]["messages"]: - var message = jsonMsg.toMessage() - if message.hasMention: - chatsWithMentions.add(message.chatId) - signal.messages.add(message) - - if event["event"]{"chats"} != nil: - for jsonChat in event["event"]["chats"]: - var chat = jsonChat.toChat - if chatsWithMentions.contains(chat.id): - chat.mentionsCount.inc - signal.chats.add(chat) - - if event["event"]{"statusUpdates"} != nil: - for jsonStatusUpdate in event["event"]["statusUpdates"]: - var statusUpdate = jsonStatusUpdate.toStatusUpdate - signal.statusUpdates.add(statusUpdate) - - if event["event"]{"installations"} != nil: - for jsonInstallation in event["event"]["installations"]: - signal.installations.add(jsonInstallation.toInstallation) - - if event["event"]{"emojiReactions"} != nil: - for jsonReaction in event["event"]["emojiReactions"]: - signal.emojiReactions.add(jsonReaction.toReaction) - - if event["event"]{"communities"} != nil: - for jsonCommunity in event["event"]["communities"]: - signal.communities.add(jsonCommunity.toCommunity) - - if event["event"]{"requestsToJoinCommunity"} != nil: - for jsonCommunity in event["event"]["requestsToJoinCommunity"]: - signal.membershipRequests.add(jsonCommunity.toCommunityMembershipRequest) - - if event["event"]{"removedMessages"} != nil: - for jsonRemovedMessage in event["event"]["removedMessages"]: - signal.deletedMessages.add(jsonRemovedMessage.toRemovedMessage) - - if event["event"]{"activityCenterNotifications"} != nil: - for jsonNotification in event["event"]["activityCenterNotifications"]: - signal.activityCenterNotification.add(jsonNotification.toActivityCenterNotification()) - - if event["event"]{"pinMessages"} != nil: - for jsonPinnedMessage in event["event"]["pinMessages"]: - var contentType: ContentType - try: - contentType = ContentType(jsonPinnedMessage{"contentType"}.getInt) - except: - warn "Unknown content type received", type = jsonPinnedMessage{"contentType"}.getInt - contentType = ContentType.Message - signal.pinnedMessages.add(Message( - id: jsonPinnedMessage{"message_id"}.getStr, - chatId: jsonPinnedMessage{"chat_id"}.getStr, - localChatId: jsonPinnedMessage{"localChatId"}.getStr, - pinnedBy: jsonPinnedMessage{"from"}.getStr, - identicon: jsonPinnedMessage{"identicon"}.getStr, - alias: jsonPinnedMessage{"alias"}.getStr, - clock: jsonPinnedMessage{"clock"}.getInt, - isPinned: jsonPinnedMessage{"pinned"}.getBool, - contentType: contentType - )) - - result = signal \ No newline at end of file diff --git a/src/app_service/signals/signal_controller.nim b/src/app_service/signals/signal_controller.nim index 18417f339f..f7569b288f 100644 --- a/src/app_service/signals/signal_controller.nim +++ b/src/app_service/signals/signal_controller.nim @@ -1,8 +1,8 @@ import NimQml, json, chronicles, strutils, json_serialization -import base, signal_type, messages, discovery_summary, whisper_filter, envelope, expired, - wallet, mailserver, community, stats -import ../../status/status -import ../../eventemitter +import status/signals/[base, signal_type, messages, discovery_summary, whisper_filter, envelope, expired, + wallet, mailserver, community, stats] +import status/status +import eventemitter logScope: topics = "signals" diff --git a/src/app_service/signals/signal_type.nim b/src/app_service/signals/signal_type.nim deleted file mode 100644 index 0a48eac022..0000000000 --- a/src/app_service/signals/signal_type.nim +++ /dev/null @@ -1,26 +0,0 @@ -{.used.} - -type SignalType* {.pure.} = enum - Message = "messages.new" - Wallet = "wallet" - NodeReady = "node.ready" - NodeCrashed = "node.crashed" - NodeStarted = "node.started" - NodeStopped = "node.stopped" - NodeLogin = "node.login" - EnvelopeSent = "envelope.sent" - EnvelopeExpired = "envelope.expired" - MailserverRequestCompleted = "mailserver.request.completed" - MailserverRequestExpired = "mailserver.request.expired" - DiscoveryStarted = "discovery.started" - DiscoveryStopped = "discovery.stopped" - DiscoverySummary = "discovery.summary" - SubscriptionsData = "subscriptions.data" - SubscriptionsError = "subscriptions.error" - WhisperFilterAdded = "whisper.filter.added" - CommunityFound = "community.found" - Stats = "stats" - Unknown - -proc event*(self:SignalType):string = - result = "signal:" & $self \ No newline at end of file diff --git a/src/app_service/signals/stats.nim b/src/app_service/signals/stats.nim deleted file mode 100644 index 5b88edf8d2..0000000000 --- a/src/app_service/signals/stats.nim +++ /dev/null @@ -1,21 +0,0 @@ -import json - -import base - -type Stats* = object - uploadRate*: uint64 - downloadRate*: uint64 - -type StatsSignal* = ref object of Signal - stats*: Stats - -proc toStats(jsonMsg: JsonNode): Stats = - result = Stats( - uploadRate: uint64(jsonMsg{"uploadRate"}.getBiggestInt()), - downloadRate: uint64(jsonMsg{"downloadRate"}.getBiggestInt()) - ) - -proc fromEvent*(event: JsonNode): Signal = - var signal:StatsSignal = StatsSignal() - signal.stats = event["event"].toStats - result = signal \ No newline at end of file diff --git a/src/app_service/signals/wallet.nim b/src/app_service/signals/wallet.nim deleted file mode 100644 index 8d52bb1d98..0000000000 --- a/src/app_service/signals/wallet.nim +++ /dev/null @@ -1,25 +0,0 @@ -import json - -import base - -type WalletSignal* = ref object of Signal - content*: string - eventType*: string - blockNumber*: int - accounts*: seq[string] - # newTransactions*: ??? - erc20*: bool - -proc fromEvent*(jsonSignal: JsonNode): Signal = - var signal:WalletSignal = WalletSignal() - signal.content = $jsonSignal - if jsonSignal["event"].kind != JNull: - signal.eventType = jsonSignal["event"]["type"].getStr - signal.blockNumber = jsonSignal["event"]{"blockNumber"}.getInt - signal.erc20 = jsonSignal["event"]{"erc20"}.getBool - signal.accounts = @[] - if jsonSignal["event"]["accounts"].kind != JNull: - for account in jsonSignal["event"]["accounts"]: - signal.accounts.add(account.getStr) - result = signal - \ No newline at end of file diff --git a/src/app_service/signals/whisper_filter.nim b/src/app_service/signals/whisper_filter.nim deleted file mode 100644 index f8f1336165..0000000000 --- a/src/app_service/signals/whisper_filter.nim +++ /dev/null @@ -1,33 +0,0 @@ -import json - -import base - -type Filter* = object - chatId*: string - symKeyId*: string - listen*: bool - filterId*: string - identity*: string - topic*: string - -type WhisperFilterSignal* = ref object of Signal - filters*: seq[Filter] - -proc toFilter(jsonMsg: JsonNode): Filter = - result = Filter( - chatId: jsonMsg{"chatId"}.getStr, - symKeyId: jsonMsg{"symKeyId"}.getStr, - listen: jsonMsg{"listen"}.getBool, - filterId: jsonMsg{"filterId"}.getStr, - identity: jsonMsg{"identity"}.getStr, - topic: jsonMsg{"topic"}.getStr, - ) - -proc fromEvent*(event: JsonNode): Signal = - var signal:WhisperFilterSignal = WhisperFilterSignal() - - if event["event"]{"filters"} != nil: - for jsonMsg in event["event"]["filters"]: - signal.filters.add(jsonMsg.toFilter) - - result = signal \ No newline at end of file diff --git a/src/app_service/tasks/marathon/mailserver/controller.nim b/src/app_service/tasks/marathon/mailserver/controller.nim index 5b7de1e29e..9ea0421f29 100644 --- a/src/app_service/tasks/marathon/mailserver/controller.nim +++ b/src/app_service/tasks/marathon/mailserver/controller.nim @@ -5,7 +5,7 @@ import # vendor libs chronicles, NimQml, json_serialization import # status-desktop libs - ../../../../status/status, ../../common as task_runner_common, ./events + status/status, ../../common as task_runner_common, ./events logScope: topics = "mailserver controller" diff --git a/src/app_service/tasks/marathon/mailserver/events.nim b/src/app_service/tasks/marathon/mailserver/events.nim index 31765d7538..9d94768f89 100644 --- a/src/app_service/tasks/marathon/mailserver/events.nim +++ b/src/app_service/tasks/marathon/mailserver/events.nim @@ -2,7 +2,7 @@ import # vendor libs NimQml, json_serialization import # status-desktop libs - ../../../../eventemitter + eventemitter type MailserverEvents* = ref object diff --git a/src/app_service/tasks/marathon/mailserver/model.nim b/src/app_service/tasks/marathon/mailserver/model.nim index 859dc8af04..bd9bbf9bbc 100644 --- a/src/app_service/tasks/marathon/mailserver/model.nim +++ b/src/app_service/tasks/marathon/mailserver/model.nim @@ -4,11 +4,11 @@ import from times import cpuTime import - ../../../../status/libstatus/settings as status_settings, - ../../../../status/libstatus/chat as status_chat, - ../../../../status/libstatus/mailservers as status_mailservers, - ../../../../status/libstatus/core as status_core, - ../../../../status/fleet, + status/libstatus/settings as status_settings, + status/libstatus/chat as status_chat, + status/libstatus/mailservers as status_mailservers, + status/libstatus/core as status_core, + status/fleet, ./events as mailserver_events logScope: diff --git a/src/app_service/tasks/marathon/mailserver/worker.nim b/src/app_service/tasks/marathon/mailserver/worker.nim index 4747172e35..0ea5a21b90 100644 --- a/src/app_service/tasks/marathon/mailserver/worker.nim +++ b/src/app_service/tasks/marathon/mailserver/worker.nim @@ -7,7 +7,7 @@ import # vendor libs import # status-desktop libs ../worker, ./model, ../../qt, ../../common as task_runner_common, ../common as methuselash_common, - ../../../../status/libstatus/mailservers # TODO: needed for MailserverTopic type, remove? + status/libstatus/mailservers # TODO: needed for MailserverTopic type, remove? export chronos, task_runner_common, json_serialization diff --git a/src/eventemitter.nim b/src/eventemitter.nim deleted file mode 100644 index 7ea5eb2c09..0000000000 --- a/src/eventemitter.nim +++ /dev/null @@ -1,52 +0,0 @@ -import # system libs - tables - -import # deps - uuids - -type - Args* = ref object of RootObj # ...args - Handler* = proc (args: Args) {.closure.} # callback function type - EventEmitter* = ref object - events: Table[string, Table[UUID, Handler]] - -proc createEventEmitter*(): EventEmitter = - result.new - result.events = initTable[string, Table[UUID, Handler]]() - - -proc on(this: EventEmitter, name: string, handlerId: UUID, handler: Handler): void = - if this.events.hasKey(name): - this.events[name].add handlerId, handler - return - - this.events[name] = [(handlerId, handler)].toTable - -proc on*(this: EventEmitter, name: string, handler: Handler): void = - var uuid: UUID - this.on(name, uuid, handler) - -proc once*(this:EventEmitter, name:string, handler:Handler): void = - var handlerId = genUUID() - this.on(name, handlerId) do(a: Args): - handler(a) - this.events[name].del handlerId - -proc emit*(this:EventEmitter, name:string, args:Args): void = - if this.events.hasKey(name): - for (id, handler) in this.events[name].pairs: - handler(args) - -when isMainModule: - block: - type ReadyArgs = ref object of Args - text: string - var evts = createEventEmitter() - evts.on("ready") do(a: Args): - var args = ReadyArgs(a) - echo args.text, ": from [1st] handler" - evts.once("ready") do(a: Args): - var args = ReadyArgs(a) - echo args.text, ": from [2nd] handler" - evts.emit("ready", ReadyArgs(text:"Hello, World")) - evts.emit("ready", ReadyArgs(text:"Hello, World")) diff --git a/src/status/accounts.nim b/src/status/accounts.nim deleted file mode 100644 index f74ca8078a..0000000000 --- a/src/status/accounts.nim +++ /dev/null @@ -1,86 +0,0 @@ -import options, chronicles, json, json_serialization, sequtils, sugar -import libstatus/accounts as status_accounts -import libstatus/settings as status_settings -import ./types/[account, fleet, sticker, setting] -import utils -import ../eventemitter - -const DEFAULT_NETWORK_NAME* = "mainnet_rpc" - -type - AccountModel* = ref object - generatedAddresses*: seq[GeneratedAccount] - nodeAccounts*: seq[NodeAccount] - events: EventEmitter - -proc newAccountModel*(events: EventEmitter): AccountModel = - result = AccountModel() - result.events = events - -proc generateAddresses*(self: AccountModel): seq[GeneratedAccount] = - var accounts = status_accounts.generateAddresses() - for account in accounts.mitems: - account.name = status_accounts.generateAlias(account.derived.whisper.publicKey) - account.identicon = status_accounts.generateIdenticon(account.derived.whisper.publicKey) - self.generatedAddresses.add(account) - result = self.generatedAddresses - -proc openAccounts*(self: AccountModel): seq[NodeAccount] = - result = status_accounts.openAccounts() - -proc login*(self: AccountModel, selectedAccountIndex: int, password: string): NodeAccount = - let currentNodeAccount = self.nodeAccounts[selectedAccountIndex] - result = status_accounts.login(currentNodeAccount, password) - -proc storeAccountAndLogin*(self: AccountModel, fleetConfig: FleetConfig, selectedAccountIndex: int, password: string): Account = - let generatedAccount: GeneratedAccount = self.generatedAddresses[selectedAccountIndex] - result = status_accounts.setupAccount(fleetConfig, generatedAccount, password) - -proc storeDerivedAndLogin*(self: AccountModel, fleetConfig: FleetConfig, importedAccount: GeneratedAccount, password: string): Account = - result = status_accounts.setupAccount(fleetConfig, importedAccount, password) - -proc importMnemonic*(self: AccountModel, mnemonic: string): GeneratedAccount = - let importedAccount = status_accounts.multiAccountImportMnemonic(mnemonic) - importedAccount.derived = status_accounts.deriveAccounts(importedAccount.id) - importedAccount.name = status_accounts.generateAlias(importedAccount.derived.whisper.publicKey) - importedAccount.identicon = status_accounts.generateIdenticon(importedAccount.derived.whisper.publicKey) - result = importedAccount - -proc reset*(self: AccountModel) = - self.nodeAccounts = @[] - self.generatedAddresses = @[] - -proc generateAlias*(publicKey: string): string = - result = status_accounts.generateAlias(publicKey) - -proc generateIdenticon*(publicKey: string): string = - result = status_accounts.generateIdenticon(publicKey) - -proc generateAlias*(self: AccountModel, publicKey: string): string = - result = generateAlias(publicKey) - -proc generateIdenticon*(self: AccountModel, publicKey: string): string = - result = generateIdenticon(publicKey) - -proc changeNetwork*(self: AccountModel, fleetConfig: FleetConfig, network: string) = - var statusGoResult = status_settings.setNetwork(network) - if statusGoResult.error != "": - error "Error saving updated node config", msg=statusGoResult.error - - # remove all installed sticker packs (pack ids do not match across networks) - statusGoResult = status_settings.saveSetting(Setting.Stickers_PacksInstalled, %* {}) - if statusGoResult.error != "": - error "Error removing all installed sticker packs", msg=statusGoResult.error - - # remove all recent stickers (pack ids do not match across networks) - statusGoResult = status_settings.saveSetting(Setting.Stickers_Recent, %* {}) - if statusGoResult.error != "": - error "Error removing all recent stickers", msg=statusGoResult.error - -proc changePassword*(self: AccountModel, keyUID: string, password: string, newPassword: string): bool = - try: - if not status_accounts.changeDatabasePassword(keyUID, password, newPassword): - return false - except: - return false - return true \ No newline at end of file diff --git a/src/status/browser.nim b/src/status/browser.nim deleted file mode 100644 index 626bef20e9..0000000000 --- a/src/status/browser.nim +++ /dev/null @@ -1,24 +0,0 @@ -import libstatus/browser as status_browser -import ../eventemitter - -import ./types/[bookmark] - -type - BrowserModel* = ref object - events*: EventEmitter - -proc newBrowserModel*(events: EventEmitter): BrowserModel = - result = BrowserModel() - result.events = events - -proc storeBookmark*(self: BrowserModel, url: string, name: string): Bookmark = - result = status_browser.storeBookmark(url, name) - -proc updateBookmark*(self: BrowserModel, ogUrl: string, url: string, name: string) = - status_browser.updateBookmark(ogUrl, url, name) - -proc getBookmarks*(self: BrowserModel): string = - result = status_browser.getBookmarks() - -proc deleteBookmark*(self: BrowserModel, url: string) = - status_browser.deleteBookmark(url) diff --git a/src/status/chat.nim b/src/status/chat.nim deleted file mode 100644 index 0f1e0551a6..0000000000 --- a/src/status/chat.nim +++ /dev/null @@ -1,763 +0,0 @@ -import json, strutils, sequtils, tables, chronicles, times, sugar -import libstatus/chat as status_chat -import libstatus/chatCommands as status_chat_commands -import types/[message, status_update, activity_center_notification, - sticker, removed_message] -import utils as status_utils -import stickers -import ../eventemitter - -import profile/profile -import contacts -import chat/[chat, utils] -import ens, accounts - -include utils/json_utils - -logScope: - topics = "chat-model" - -const backToFirstChat* = "__goBackToFirstChat" -const ZERO_ADDRESS* = "0x0000000000000000000000000000000000000000" - -type - ChatUpdateArgs* = ref object of Args - chats*: seq[Chat] - messages*: seq[Message] - pinnedMessages*: seq[Message] - contacts*: seq[Profile] - emojiReactions*: seq[Reaction] - communities*: seq[Community] - communityMembershipRequests*: seq[CommunityMembershipRequest] - activityCenterNotifications*: seq[ActivityCenterNotification] - statusUpdates*: seq[StatusUpdate] - deletedMessages*: seq[RemovedMessage] - - ChatIdArg* = ref object of Args - chatId*: string - - ChannelArgs* = ref object of Args - chat*: Chat - - ChatArgs* = ref object of Args - chats*: seq[Chat] - - CommunityActiveChangedArgs* = ref object of Args - active*: bool - - MsgsLoadedArgs* = ref object of Args - chatId*: string - messages*: seq[Message] - statusUpdates*: seq[StatusUpdate] - - ActivityCenterNotificationsArgs* = ref object of Args - activityCenterNotifications*: seq[ActivityCenterNotification] - - ReactionsLoadedArgs* = ref object of Args - reactions*: seq[Reaction] - - MessageArgs* = ref object of Args - id*: string - channel*: string - - MessageSendingSuccess* = ref object of Args - chat*: Chat - message*: Message - - MarkAsReadNotificationProperties* = ref object of Args - communityId*: string - channelId*: string - notificationTypes*: seq[ActivityCenterNotificationType] - -type ChatModel* = ref object - publicKey*: string - events*: EventEmitter - communitiesToFetch*: seq[string] - mailserverReady*: bool - contacts*: Table[string, Profile] - channels*: Table[string, Chat] - msgCursor: Table[string, string] - pinnedMsgCursor: Table[string, string] - activityCenterCursor*: string - emojiCursor: Table[string, string] - lastMessageTimestamps*: Table[string, int64] - -proc newChatModel*(events: EventEmitter): ChatModel = - result = ChatModel() - result.events = events - result.mailserverReady = false - result.communitiesToFetch = @[] - result.contacts = initTable[string, Profile]() - result.channels = initTable[string, Chat]() - result.msgCursor = initTable[string, string]() - result.pinnedMsgCursor = initTable[string, string]() - result.emojiCursor = initTable[string, string]() - result.lastMessageTimestamps = initTable[string, int64]() - -proc update*(self: ChatModel, chats: seq[Chat], messages: seq[Message], emojiReactions: seq[Reaction], communities: seq[Community], communityMembershipRequests: seq[CommunityMembershipRequest], pinnedMessages: seq[Message], activityCenterNotifications: seq[ActivityCenterNotification], statusUpdates: seq[StatusUpdate], deletedMessages: seq[RemovedMessage]) = - for chat in chats: - self.channels[chat.id] = chat - - for message in messages: - let chatId = message.chatId - let ts = times.convert(Milliseconds, Seconds, message.whisperTimestamp.parseInt()) - if not self.lastMessageTimestamps.hasKey(chatId): - self.lastMessageTimestamps[chatId] = ts - else: - if self.lastMessageTimestamps[chatId] > ts: - self.lastMessageTimestamps[chatId] = ts - - self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages,chats: chats, contacts: @[], emojiReactions: emojiReactions, communities: communities, communityMembershipRequests: communityMembershipRequests, pinnedMessages: pinnedMessages, activityCenterNotifications: activityCenterNotifications, statusUpdates: statusUpdates, deletedMessages: deletedMessages)) - -proc parseChatResponse(self: ChatModel, response: string): (seq[Chat], seq[Message]) = - var parsedResponse = parseJson(response) - var chats: seq[Chat] = @[] - var messages: seq[Message] = @[] - if parsedResponse{"result"}{"messages"} != nil: - for jsonMsg in parsedResponse["result"]["messages"]: - messages.add(jsonMsg.toMessage()) - if parsedResponse{"result"}{"chats"} != nil: - for jsonChat in parsedResponse["result"]["chats"]: - let chat = jsonChat.toChat - self.channels[chat.id] = chat - chats.add(chat) - result = (chats, messages) - -proc emitUpdate(self: ChatModel, response: string) = - var (chats, messages) = self.parseChatResponse(response) - self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[])) - -proc removeFiltersByChatId(self: ChatModel, chatId: string, filters: JsonNode) - -proc removeChatFilters(self: ChatModel, chatId: string) = - # TODO: this code should be handled by status-go / stimbus instead of the client - # Clients should not have to care about filters. For more info about filters: - # https://github.com/status-im/specs/blob/master/docs/stable/3-whisper-usage.md#keys-management - let filters = parseJson(status_chat.loadFilters(@[]))["result"] - - case self.channels[chatId].chatType - of ChatType.Public: - for filter in filters: - if filter["chatId"].getStr == chatId: - status_chat.removeFilters(chatId, filter["filterId"].getStr) - of ChatType.OneToOne, ChatType.Profile: - # Check if user does not belong to any active chat group - var inGroup = false - for channel in self.channels.values: - if channel.isActive and channel.id != chatId and channel.chatType == ChatType.PrivateGroupChat: - inGroup = true - break - if not inGroup: self.removeFiltersByChatId(chatId, filters) - of ChatType.PrivateGroupChat: - for member in self.channels[chatId].members: - # Check that any of the members are not in other active group chats, or that you don’t have a one-to-one open. - var hasConversation = false - for channel in self.channels.values: - if (channel.isActive and channel.chatType == ChatType.OneToOne and channel.id == member.id) or - (channel.isActive and channel.id != chatId and channel.chatType == ChatType.PrivateGroupChat and channel.isMember(member.id)): - hasConversation = true - break - if not hasConversation: self.removeFiltersByChatId(member.id, filters) - else: - error "Unknown chat type removed", chatId - -proc removeFiltersByChatId(self: ChatModel, chatId: string, filters: JsonNode) = - var partitionedTopic = "" - for filter in filters: - # Contact code filter should be removed - if filter["identity"].getStr == chatId and filter["chatId"].getStr.endsWith("-contact-code"): - status_chat.removeFilters(chatId, filter["filterId"].getStr) - - # Remove partitioned topic if no other user in an active group chat or one-to-one is from the - # same partitioned topic - if filter["identity"].getStr == chatId and filter["chatId"].getStr.startsWith("contact-discovery-"): - partitionedTopic = filter["topic"].getStr - var samePartitionedTopic = false - for f in filters.filterIt(it["topic"].getStr == partitionedTopic and it["filterId"].getStr != filter["filterId"].getStr): - let fIdentity = f["identity"].getStr; - if self.channels.hasKey(fIdentity) and self.channels[fIdentity].isActive: - samePartitionedTopic = true - break - if not samePartitionedTopic: - status_chat.removeFilters(chatId, filter["filterId"].getStr) - -proc hasChannel*(self: ChatModel, chatId: string): bool = - self.channels.hasKey(chatId) - -proc getActiveChannel*(self: ChatModel): string = - if (self.channels.len == 0): "" else: toSeq(self.channels.values)[self.channels.len - 1].id - -proc emitTopicAndJoin(self: ChatModel, chat: Chat) = - let filterResult = status_chat.loadFilters(@[status_chat.buildFilter(chat)]) - self.events.emit("channelJoined", ChannelArgs(chat: chat)) - -proc join*(self: ChatModel, chatId: string, chatType: ChatType, ensName: string = "", pubKey: string = "") = - if self.hasChannel(chatId): return - var chat = newChat(chatId, ChatType(chatType)) - self.channels[chat.id] = chat - status_chat.saveChat(chatId, chatType, color=chat.color, ensName=ensName, profile=pubKey) - self.emitTopicAndJoin(chat) - -proc createOneToOneChat*(self: ChatModel, publicKey: string, ensName: string = "") = - if self.hasChannel(publicKey): - self.emitTopicAndJoin(self.channels[publicKey]) - return - - var chat = newChat(publicKey, ChatType.OneToOne) - if ensName != "": - chat.name = ensName - chat.ensName = ensName - self.channels[chat.id] = chat - discard status_chat.createOneToOneChat(publicKey) - self.emitTopicAndJoin(chat) - -proc createPublicChat*(self: ChatModel, chatId: string) = - if self.hasChannel(chatId): return - var chat = newChat(chatId, ChatType.Public) - self.channels[chat.id] = chat - discard status_chat.createPublicChat(chatId) - self.emitTopicAndJoin(chat) - - -proc updateContacts*(self: ChatModel, contacts: seq[Profile]) = - for c in contacts: - self.contacts[c.id] = c - self.events.emit("chatUpdate", ChatUpdateArgs(contacts: contacts)) - -proc requestMissingCommunityInfos*(self: ChatModel) = - if (self.communitiesToFetch.len == 0): - return - for communityId in self.communitiesToFetch: - status_chat.requestCommunityInfo(communityId) - -proc init*(self: ChatModel, pubKey: string) = - self.publicKey = pubKey - - var contacts = getAddedContacts() - var chatList = status_chat.loadChats() - - let profileUpdatesChatIds = chatList.filter(c => c.chatType == ChatType.Profile).map(c => c.id) - - if chatList.filter(c => c.chatType == ChatType.Timeline).len == 0: - var timelineChannel = newChat(status_utils.getTimelineChatId(), ChatType.Timeline) - self.join(timelineChannel.id, timelineChannel.chatType) - chatList.add(timelineChannel) - - let timelineChatId = status_utils.getTimelineChatId(pubKey) - - if not profileUpdatesChatIds.contains(timelineChatId): - var profileUpdateChannel = newChat(timelineChatId, ChatType.Profile) - status_chat.saveChat(profileUpdateChannel.id, profileUpdateChannel.chatType, profile=pubKey) - chatList.add(profileUpdateChannel) - - # For profile updates and timeline, we have to make sure that for - # each added contact, a chat has been saved for the currently logged-in - # user. Users that will use a version of Status with timeline support for the - # first time, won't have any of those otherwise. - if profileUpdatesChatIds.filter(id => id != timelineChatId).len != contacts.len: - for contact in contacts: - if not profileUpdatesChatIds.contains(status_utils.getTimelineChatId(contact.address)): - let profileUpdatesChannel = newChat(status_utils.getTimelineChatId(contact.address), ChatType.Profile) - status_chat.saveChat(profileUpdatesChannel.id, profileUpdatesChannel.chatType, ensName=contact.ensName, profile=contact.address) - chatList.add(profileUpdatesChannel) - - var filters:seq[JsonNode] = @[] - for chat in chatList: - if self.hasChannel(chat.id): - continue - filters.add status_chat.buildFilter(chat) - self.channels[chat.id] = chat - self.events.emit("channelLoaded", ChannelArgs(chat: chat)) - - if filters.len == 0: return - - let filterResult = status_chat.loadFilters(filters) - - self.events.emit("chatsLoaded", ChatArgs(chats: chatList)) - - - self.events.once("mailserverAvailable") do(a: Args): - self.mailserverReady = true - self.requestMissingCommunityInfos() - - self.events.on("contactUpdate") do(a: Args): - var evArgs = ContactUpdateArgs(a) - self.updateContacts(evArgs.contacts) - -proc statusUpdates*(self: ChatModel) = - let statusUpdates = status_chat.statusUpdates() - self.events.emit("messagesLoaded", MsgsLoadedArgs(statusUpdates: statusUpdates)) - -proc leave*(self: ChatModel, chatId: string) = - self.removeChatFilters(chatId) - - if self.channels[chatId].chatType == ChatType.PrivateGroupChat: - let leaveGroupResponse = status_chat.leaveGroupChat(chatId) - self.emitUpdate(leaveGroupResponse) - - discard status_chat.deactivateChat(self.channels[chatId]) - - self.channels.del(chatId) - discard status_chat.clearChatHistory(chatId) - self.events.emit("channelLeft", ChatIdArg(chatId: chatId)) - -proc clearHistory*(self: ChatModel, chatId: string) = - discard status_chat.clearChatHistory(chatId) - let chat = self.channels[chatId] - self.events.emit("chatHistoryCleared", ChannelArgs(chat: chat)) - -proc setActiveChannel*(self: ChatModel, chatId: string) = - self.events.emit("activeChannelChanged", ChatIdArg(chatId: chatId)) - -proc processMessageUpdateAfterSend(self: ChatModel, response: string): (seq[Chat], seq[Message]) = - result = self.parseChatResponse(response) - var (chats, messages) = result - if chats.len == 0 and messages.len == 0: - self.events.emit("messageSendingFailed", Args()) - return - - self.events.emit("messageSendingSuccess", MessageSendingSuccess(message: messages[0], chat: chats[0])) - -proc sendMessage*(self: ChatModel, chatId: string, msg: string, replyTo: string = "", contentType: int = ContentType.Message.int, communityId: string = "") = - var response = status_chat.sendChatMessage(chatId, msg, replyTo, contentType, communityId) - discard self.processMessageUpdateAfterSend(response) - -proc editMessage*(self: ChatModel, messageId: string, msg: string) = - var response = status_chat.editMessage(messageId, msg) - discard self.processMessageUpdateAfterSend(response) - -proc sendImage*(self: ChatModel, chatId: string, image: string) = - var response = status_chat.sendImageMessage(chatId, image) - discard self.processMessageUpdateAfterSend(response) - -proc sendImages*(self: ChatModel, chatId: string, images: var seq[string]) = - var response = status_chat.sendImageMessages(chatId, images) - discard self.processMessageUpdateAfterSend(response) - -proc deleteMessageAndSend*(self: ChatModel, messageId: string) = - var response = status_chat.deleteMessageAndSend(messageId) - discard self.processMessageUpdateAfterSend(response) - -proc sendSticker*(self: ChatModel, chatId: string, replyTo: string, sticker: Sticker) = - var response = status_chat.sendStickerMessage(chatId, replyTo, sticker) - self.events.emit("stickerSent", StickerArgs(sticker: sticker, save: true)) - var (chats, messages) = self.parseChatResponse(response) - self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[])) - self.events.emit("sendingMessage", MessageArgs(id: messages[0].id, channel: messages[0].chatId)) - -proc addEmojiReaction*(self: ChatModel, chatId: string, messageId: string, emojiId: int) = - let reactions = status_chat.addEmojiReaction(chatId, messageId, emojiId) - self.events.emit("reactionsLoaded", ReactionsLoadedArgs(reactions: reactions)) - -proc removeEmojiReaction*(self: ChatModel, emojiReactionId: string) = - let reactions = status_chat.removeEmojiReaction(emojiReactionId) - self.events.emit("reactionsLoaded", ReactionsLoadedArgs(reactions: reactions)) - -proc onMarkMessagesRead(self: ChatModel, response: string, chatId: string): JsonNode = - result = parseJson(response) - if self.channels.hasKey(chatId): - self.channels[chatId].unviewedMessagesCount = 0 - self.channels[chatId].mentionsCount = 0 - self.events.emit("channelUpdate", ChatUpdateArgs(messages: @[], chats: @[self.channels[chatId]], contacts: @[])) - -proc onAsyncMarkMessagesRead*(self: ChatModel, response: string) = - let parsedResponse = parseJson(response) - discard self.onMarkMessagesRead(parsedResponse{"response"}.getStr, parsedResponse{"chatId"}.getStr) - -proc markAllChannelMessagesRead*(self: ChatModel, chatId: string): JsonNode = - var response = status_chat.markAllRead(chatId) - return self.onMarkMessagesRead(response, chatId) - -proc markMessagesSeen*(self: ChatModel, chatId: string, messageIds: seq[string]): JsonNode = - var response = status_chat.markMessagesSeen(chatId, messageIds) - return self.onMarkMessagesRead(response, chatId) - -proc confirmJoiningGroup*(self: ChatModel, chatId: string) = - var response = status_chat.confirmJoiningGroup(chatId) - self.emitUpdate(response) - -proc renameGroup*(self: ChatModel, chatId: string, newName: string) = - var response = status_chat.renameGroup(chatId, newName) - self.emitUpdate(response) - -proc getUserName*(self: ChatModel, id: string, defaultUserName: string):string = - if(self.contacts.hasKey(id)): - return userNameOrAlias(self.contacts[id]) - else: - return defaultUserName - -proc processGroupChatCreation*(self: ChatModel, result: string) = - var response = parseJson(result) - var (chats, messages) = formatChatUpdate(response) - let chat = chats[0] - self.channels[chat.id] = chat - self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[])) - self.events.emit("activeChannelChanged", ChatIdArg(chatId: chat.id)) - -proc createGroup*(self: ChatModel, groupName: string, pubKeys: seq[string]) = - var result = status_chat.createGroup(groupName, pubKeys) - self.processGroupChatCreation(result) - -proc createGroupChatFromInvitation*(self: ChatModel, groupName: string, chatID: string, adminPK: string) = - var result = status_chat.createGroupChatFromInvitation(groupName, chatID, adminPK) - self.processGroupChatCreation(result) - -proc addGroupMembers*(self: ChatModel, chatId: string, pubKeys: seq[string]) = - var response = status_chat.addGroupMembers(chatId, pubKeys) - self.emitUpdate(response) - -proc kickGroupMember*(self: ChatModel, chatId: string, pubKey: string) = - var response = status_chat.kickGroupMember(chatId, pubKey) - self.emitUpdate(response) - -proc makeAdmin*(self: ChatModel, chatId: string, pubKey: string) = - var response = status_chat.makeAdmin(chatId, pubKey) - self.emitUpdate(response) - -proc resendMessage*(self: ChatModel, messageId: string) = - discard status_chat.reSendChatMessage(messageId) - -proc muteChat*(self: ChatModel, chat: Chat) = - discard status_chat.muteChat(chat.id) - self.events.emit("chatUpdate", ChatUpdateArgs(messages: @[], chats: @[chat], contacts: @[])) - -proc unmuteChat*(self: ChatModel, chat: Chat) = - discard status_chat.unmuteChat(chat.id) - self.events.emit("chatUpdate", ChatUpdateArgs(messages: @[], chats: @[chat], contacts: @[])) - -proc processUpdateForTransaction*(self: ChatModel, messageId: string, response: string) = - var (chats, messages) = self.processMessageUpdateAfterSend(response) - self.events.emit("messageDeleted", MessageArgs(id: messageId, channel: chats[0].id)) - -proc acceptRequestAddressForTransaction*(self: ChatModel, messageId: string, address: string) = - let response = status_chat_commands.acceptRequestAddressForTransaction(messageId, address) - self.processUpdateForTransaction(messageId, response) - -proc declineRequestAddressForTransaction*(self: ChatModel, messageId: string) = - let response = status_chat_commands.declineRequestAddressForTransaction(messageId) - self.processUpdateForTransaction(messageId, response) - -proc declineRequestTransaction*(self: ChatModel, messageId: string) = - let response = status_chat_commands.declineRequestTransaction(messageId) - self.processUpdateForTransaction(messageId, response) - -proc requestAddressForTransaction*(self: ChatModel, chatId: string, fromAddress: string, amount: string, tokenAddress: string) = - let address = if (tokenAddress == ZERO_ADDRESS): "" else: tokenAddress - let response = status_chat_commands.requestAddressForTransaction(chatId, fromAddress, amount, address) - discard self.processMessageUpdateAfterSend(response) - -proc acceptRequestTransaction*(self: ChatModel, transactionHash: string, messageId: string, signature: string) = - let response = status_chat_commands.acceptRequestTransaction(transactionHash, messageId, signature) - discard self.processMessageUpdateAfterSend(response) - -proc requestTransaction*(self: ChatModel, chatId: string, fromAddress: string, amount: string, tokenAddress: string) = - let address = if (tokenAddress == ZERO_ADDRESS): "" else: tokenAddress - let response = status_chat_commands.requestTransaction(chatId, fromAddress, amount, address) - discard self.processMessageUpdateAfterSend(response) - -proc getAllComunities*(self: ChatModel): seq[Community] = - result = status_chat.getAllComunities() - -proc getJoinedComunities*(self: ChatModel): seq[Community] = - result = status_chat.getJoinedComunities() - -proc createCommunity*(self: ChatModel, name: string, description: string, access: int, ensOnly: bool, color: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int): Community = - result = status_chat.createCommunity(name, description, access, ensOnly, color, imageUrl, aX, aY, bX, bY) - -proc editCommunity*(self: ChatModel, id: string, name: string, description: string, access: int, ensOnly: bool, color: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int): Community = - result = status_chat.editCommunity(id, name, description, access, ensOnly, color, imageUrl, aX, aY, bX, bY) - -proc createCommunityChannel*(self: ChatModel, communityId: string, name: string, description: string): Chat = - result = status_chat.createCommunityChannel(communityId, name, description) - -proc editCommunityChannel*(self: ChatModel, communityId: string, channelId: string, name: string, description: string, categoryId: string): Chat = - result = status_chat.editCommunityChannel(communityId, channelId, name, description, categoryId) - -proc deleteCommunityChat*(self: ChatModel, communityId: string, channelId: string) = - status_chat.deleteCommunityChat(communityId, channelId) - -proc reorderCommunityCategories*(self: ChatModel, communityId: string, categoryId: string, position: int) = - status_chat.reorderCommunityCategories(communityId, categoryId, position) - -proc createCommunityCategory*(self: ChatModel, communityId: string, name: string, channels: seq[string]): CommunityCategory = - result = status_chat.createCommunityCategory(communityId, name, channels) - -proc editCommunityCategory*(self: ChatModel, communityId: string, categoryId: string, name: string, channels: seq[string]) = - status_chat.editCommunityCategory(communityId, categoryId, name, channels) - -proc deleteCommunityCategory*(self: ChatModel, communityId: string, categoryId: string) = - status_chat.deleteCommunityCategory(communityId, categoryId) - -proc reorderCommunityChannel*(self: ChatModel, communityId: string, categoryId: string, chatId: string, position: int) = - status_chat.reorderCommunityChat(communityId, categoryId, chatId, position) - -proc joinCommunity*(self: ChatModel, communityId: string) = - status_chat.joinCommunity(communityId) - -proc requestCommunityInfo*(self: ChatModel, communityId: string) = - if (not self.mailserverReady): - self.communitiesToFetch.add(communityId) - self.communitiesToFetch = self.communitiesToFetch.deduplicate() - return - status_chat.requestCommunityInfo(communityId) - -proc leaveCommunity*(self: ChatModel, communityId: string) = - status_chat.leaveCommunity(communityId) - -proc inviteUserToCommunity*(self: ChatModel, communityId: string, pubKey: string) = - status_chat.inviteUsersToCommunity(communityId, @[pubKey]) - -proc inviteUsersToCommunity*(self: ChatModel, communityId: string, pubKeys: seq[string]) = - status_chat.inviteUsersToCommunity(communityId, pubKeys) - -proc removeUserFromCommunity*(self: ChatModel, communityId: string, pubKey: string) = - status_chat.removeUserFromCommunity(communityId, pubKey) - -proc banUserFromCommunity*(self: ChatModel, pubKey: string, communityId: string): string = - return status_chat.banUserFromCommunity(pubKey, communityId) - -proc exportCommunity*(self: ChatModel, communityId: string): string = - result = status_chat.exportCommunity(communityId) - -proc importCommunity*(self: ChatModel, communityKey: string): string = - result = status_chat.importCommunity(communityKey) - -proc requestToJoinCommunity*(self: ChatModel, communityKey: string, ensName: string): seq[CommunityMembershipRequest] = - status_chat.requestToJoinCommunity(communityKey, ensName) - -proc acceptRequestToJoinCommunity*(self: ChatModel, requestId: string) = - status_chat.acceptRequestToJoinCommunity(requestId) - -proc declineRequestToJoinCommunity*(self: ChatModel, requestId: string) = - status_chat.declineRequestToJoinCommunity(requestId) - -proc pendingRequestsToJoinForCommunity*(self: ChatModel, communityKey: string): seq[CommunityMembershipRequest] = - result = status_chat.pendingRequestsToJoinForCommunity(communityKey) - -proc setCommunityMuted*(self: ChatModel, communityId: string, muted: bool) = - status_chat.setCommunityMuted(communityId, muted) - -proc myPendingRequestsToJoin*(self: ChatModel): seq[CommunityMembershipRequest] = - result = status_chat.myPendingRequestsToJoin() - -proc setPinMessage*(self: ChatModel, messageId: string, chatId: string, pinned: bool) = - status_chat.setPinMessage(messageId, chatId, pinned) - -proc activityCenterNotifications*(self: ChatModel, initialLoad: bool = true) = - # Notifications were already loaded, since cursor will - # be nil/empty if there are no more notifs - if(not initialLoad and self.activityCenterCursor == ""): return - - let activityCenterNotificationsTuple = status_chat.activityCenterNotification(self.activityCenterCursor) - self.activityCenterCursor = activityCenterNotificationsTuple[0]; - - self.events.emit("activityCenterNotificationsLoaded", ActivityCenterNotificationsArgs(activityCenterNotifications: activityCenterNotificationsTuple[1])) - -proc activityCenterNotifications*(self: ChatModel, cursor: string = "", activityCenterNotifications: seq[ActivityCenterNotification]) = - self.activityCenterCursor = cursor - - self.events.emit("activityCenterNotificationsLoaded", ActivityCenterNotificationsArgs(activityCenterNotifications: activityCenterNotifications)) - -proc markAllActivityCenterNotificationsRead*(self: ChatModel): string = - try: - status_chat.markAllActivityCenterNotificationsRead() - except Exception as e: - error "Error marking all as read", msg = e.msg - result = e.msg - - # This proc should accept ActivityCenterNotificationType in order to clear all notifications - # per type, that's why we have this part here. If we add all types to notificationsType that - # means that we need to clear all notifications for all types. - var types : seq[ActivityCenterNotificationType] - for t in ActivityCenterNotificationType: - types.add(t) - - self.events.emit("markNotificationsAsRead", MarkAsReadNotificationProperties(notificationTypes: types)) - -proc markActivityCenterNotificationRead*(self: ChatModel, notificationId: string, -markAsReadProps: MarkAsReadNotificationProperties): string = - try: - status_chat.markActivityCenterNotificationsRead(@[notificationId]) - except Exception as e: - error "Error marking as read", msg = e.msg - result = e.msg - - self.events.emit("markNotificationsAsRead", markAsReadProps) - -proc acceptActivityCenterNotifications*(self: ChatModel, ids: seq[string]): string = - try: - let response = status_chat.acceptActivityCenterNotifications(ids) - - let (chats, messages) = self.parseChatResponse(response) - self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats)) - - except Exception as e: - error "Error marking as accepted", msg = e.msg - result = e.msg - -proc dismissActivityCenterNotifications*(self: ChatModel, ids: seq[string]): string = - try: - discard status_chat.dismissActivityCenterNotifications(ids) - except Exception as e: - error "Error marking as dismissed", msg = e.msg - result = e.msg - -proc unreadActivityCenterNotificationsCount*(self: ChatModel): int = - status_chat.unreadActivityCenterNotificationsCount() - -proc getLinkPreviewData*(link: string, success: var bool): JsonNode = - result = status_chat.getLinkPreviewData(link, success) - -proc getCommunityIdForChat*(self: ChatModel, chatId: string): string = - if (not self.hasChannel(chatId)): - return "" - return self.channels[chatId].communityId - -proc onAsyncSearchMessages*(self: ChatModel, response: string) = - let responseObj = response.parseJson - if (responseObj.kind != JObject): - info "search messages response is not an json object" - return - - var chatId: string - discard responseObj.getProp("chatId", chatId) - - var messagesObj: JsonNode - if (not responseObj.getProp("messages", messagesObj)): - info "search messages response doesn't contain messages property" - return - - var messagesArray: JsonNode - if (not messagesObj.getProp("messages", messagesArray)): - info "search messages response doesn't contain messages array" - return - - var messages: seq[Message] = @[] - if (messagesArray.kind == JArray): - for jsonMsg in messagesArray: - messages.add(jsonMsg.toMessage()) - - self.events.emit("searchMessagesLoaded", MsgsLoadedArgs(chatId: chatId, messages: messages)) - -proc onLoadMoreMessagesForChannel*(self: ChatModel, response: string) = - let responseObj = response.parseJson - if (responseObj.kind != JObject): - info "load more messages response is not an json object" - - # notify view - self.events.emit("messagesLoaded", MsgsLoadedArgs()) - self.events.emit("reactionsLoaded", ReactionsLoadedArgs()) - self.events.emit("pinnedMessagesLoaded", MsgsLoadedArgs()) - return - - var chatId: string - discard responseObj.getProp("chatId", chatId) - - # handling chat messages - var chatMessagesObj: JsonNode - var chatCursor: string - discard responseObj.getProp("messages", chatMessagesObj) - discard responseObj.getProp("messagesCursor", chatCursor) - - self.msgCursor[chatId] = chatCursor - - var messages: seq[Message] = @[] - if (chatMessagesObj.kind == JArray): - for jsonMsg in chatMessagesObj: - messages.add(jsonMsg.toMessage()) - - if messages.len > 0: - let lastMsgIndex = messages.len - 1 - let ts = times.convert(Milliseconds, Seconds, messages[lastMsgIndex].whisperTimestamp.parseInt()) - self.lastMessageTimestamps[chatId] = ts - - # handling reactions - var reactionsObj: JsonNode - var reactionsCursor: string - discard responseObj.getProp("reactions", reactionsObj) - discard responseObj.getProp("reactionsCursor", reactionsCursor) - - self.emojiCursor[chatId] = reactionsCursor; - - var reactions: seq[Reaction] = @[] - if (reactionsObj.kind == JArray): - for jsonMsg in reactionsObj: - reactions.add(jsonMsg.toReaction) - - # handling pinned messages - var pinnedMsgObj: JsonNode - var pinnedMsgCursor: string - discard responseObj.getProp("pinnedMessages", pinnedMsgObj) - discard responseObj.getProp("pinnedMessagesCursor", pinnedMsgCursor) - - self.pinnedMsgCursor[chatId] = pinnedMsgCursor - - var pinnedMessages: seq[Message] = @[] - if (pinnedMsgObj.kind == JArray): - for jsonMsg in pinnedMsgObj: - var msgObj: JsonNode - if(jsonMsg.getProp("message", msgObj)): - var msg: Message - msg = msgObj.toMessage() - discard jsonMsg.getProp("pinnedBy", msg.pinnedBy) - pinnedMessages.add(msg) - - # notify view - self.events.emit("messagesLoaded", MsgsLoadedArgs(chatId: chatId, messages: messages)) - self.events.emit("reactionsLoaded", ReactionsLoadedArgs(reactions: reactions)) - self.events.emit("pinnedMessagesLoaded", MsgsLoadedArgs(chatId: chatId, messages: pinnedMessages)) - -proc userNameOrAlias*(self: ChatModel, pubKey: string, - prettyForm: bool = false): string = - ## Returns ens name or alias, in case if prettyForm is true and ens name - ## ends with ".stateofus.eth" that part will be removed. - var alias: string - if self.contacts.hasKey(pubKey): - alias = ens.userNameOrAlias(self.contacts[pubKey]) - else: - alias = generateAlias(pubKey) - - if (prettyForm and alias.endsWith(".stateofus.eth")): - alias = alias[0 .. ^15] - - return alias - -proc chatName*(self: ChatModel, chatItem: Chat): string = - if (not chatItem.chatType.isOneToOne): - return chatItem.name - - if (self.contacts.hasKey(chatItem.id) and - self.contacts[chatItem.id].hasNickname()): - return self.contacts[chatItem.id].localNickname - - if chatItem.ensName != "": - return "@" & userName(chatItem.ensName).userName(true) - - return self.userNameOrAlias(chatItem.id) - -proc isMessageCursorSet*(self: ChatModel, channelId: string): bool = - self.msgCursor.hasKey(channelId) - -proc getCurrentMessageCursor*(self: ChatModel, channelId: string): string = - if(not self.msgCursor.hasKey(channelId)): - self.msgCursor[channelId] = "" - - return self.msgCursor[channelId] - -proc isEmojiCursorSet*(self: ChatModel, channelId: string): bool = - self.emojiCursor.hasKey(channelId) - -proc getCurrentEmojiCursor*(self: ChatModel, channelId: string): string = - if(not self.emojiCursor.hasKey(channelId)): - self.emojiCursor[channelId] = "" - - return self.emojiCursor[channelId] - -proc isPinnedMessageCursorSet*(self: ChatModel, channelId: string): bool = - self.pinnedMsgCursor.hasKey(channelId) - -proc getCurrentPinnedMessageCursor*(self: ChatModel, channelId: string): string = - if(not self.pinnedMsgCursor.hasKey(channelId)): - self.pinnedMsgCursor[channelId] = "" - - return self.pinnedMsgCursor[channelId] \ No newline at end of file diff --git a/src/status/chat/chat.nim b/src/status/chat/chat.nim deleted file mode 100644 index 693447d99a..0000000000 --- a/src/status/chat/chat.nim +++ /dev/null @@ -1,76 +0,0 @@ -import ../types/[chat, community] - -export chat, community - -proc findIndexById*(self: seq[Chat], id: string): int = - result = -1 - var idx = -1 - for item in self: - inc idx - if(item.id == id): - result = idx - break - -proc findIndexById*(self: seq[Community], id: string): int = - result = -1 - var idx = -1 - for item in self: - inc idx - if(item.id == id): - result = idx - break - -proc findIndexById*(self: seq[CommunityMembershipRequest], id: string): int = - result = -1 - var idx = -1 - for item in self: - inc idx - if(item.id == id): - result = idx - break - -proc findIndexById*(self: seq[CommunityCategory], id: string): int = - result = -1 - var idx = -1 - for item in self: - inc idx - if(item.id == id): - result = idx - break - -proc isMember*(self: Chat, pubKey: string): bool = - for member in self.members: - if member.id == pubKey: - return member.joined - return false - -proc isMemberButNotJoined*(self: Chat, pubKey: string): bool = - for member in self.members: - if member.id == pubKey: - return not member.joined - return false - -proc contains*(self: Chat, pubKey: string): bool = - for member in self.members: - if member.id == pubKey: return true - return false - -proc isAdmin*(self: Chat, pubKey: string): bool = - for member in self.members: - if member.id == pubKey: - return member.joined and member.admin - return false - -proc recalculateUnviewedMessages*(community: var Community) = - var total = 0 - for chat in community.chats: - total += chat.unviewedMessagesCount - - community.unviewedMessagesCount = total - -proc recalculateMentions*(community: var Community) = - var total = 0 - for chat in community.chats: - total += chat.unviewedMentionsCount - - community.unviewedMentionsCount = total diff --git a/src/status/chat/stickers.nim b/src/status/chat/stickers.nim deleted file mode 100644 index 30e6fe6ce6..0000000000 --- a/src/status/chat/stickers.nim +++ /dev/null @@ -1,9 +0,0 @@ -import chronicles -import ../stickers as status_stickers - -logScope: - topics = "sticker-decoding" - -# TODO: this is for testing purposes, the correct function should decode the hash -proc decodeContentHash*(value: string): string = - status_stickers.decodeContentHash(value) diff --git a/src/status/chat/utils.nim b/src/status/chat/utils.nim deleted file mode 100644 index e7d941f864..0000000000 --- a/src/status/chat/utils.nim +++ /dev/null @@ -1,13 +0,0 @@ -import json -import ../types/[message, chat] - -proc formatChatUpdate*(response: JsonNode): (seq[Chat], seq[Message]) = - var chats: seq[Chat] = @[] - var messages: seq[Message] = @[] - if response["result"]{"messages"} != nil: - for jsonMsg in response["result"]["messages"]: - messages.add(jsonMsg.toMessage()) - if response["result"]{"chats"} != nil: - for jsonChat in response["result"]["chats"]: - chats.add(jsonChat.toChat) - result = (chats, messages) \ No newline at end of file diff --git a/src/status/constants.nim b/src/status/constants.nim deleted file mode 100644 index 1a58ccd0bd..0000000000 --- a/src/status/constants.nim +++ /dev/null @@ -1,10 +0,0 @@ -import libstatus/accounts/constants - -export DATADIR -export STATUSGODIR -export KEYSTOREDIR -export TMPDIR -export LOGDIR - -const APP_UPDATES_ENS* = "desktop.status.eth" -const CHECK_VERSION_TIMEOUT_MS* = 5000 diff --git a/src/status/contacts.nim b/src/status/contacts.nim deleted file mode 100644 index ffb3690fc1..0000000000 --- a/src/status/contacts.nim +++ /dev/null @@ -1,151 +0,0 @@ -import json, sequtils, sugar, chronicles -import libstatus/contacts as status_contacts -import libstatus/accounts as status_accounts -import libstatus/chat as status_chat -import profile/profile -import ../eventemitter - -const DELETE_CONTACT* = "__deleteThisContact__" - -type - ContactModel* = ref object - events*: EventEmitter - -type - ContactUpdateArgs* = ref object of Args - contacts*: seq[Profile] - -proc newContactModel*(events: EventEmitter): ContactModel = - result = ContactModel() - result.events = events - -proc getContactByID*(self: ContactModel, id: string): Profile = - let response = status_contacts.getContactByID(id) - # TODO: change to options - let responseResult = parseJSON($response)["result"] - if responseResult == nil or responseResult.kind == JNull: - result = nil - else: - result = toProfileModel(parseJSON($response)["result"]) - -proc blockContact*(self: ContactModel, id: string): string = - var contact = self.getContactByID(id) - contact.systemTags.add(contactBlocked) - discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, contact.identityImage.thumbnail, contact.systemTags, contact.localNickname) - self.events.emit("contactBlocked", Args()) - -proc unblockContact*(self: ContactModel, id: string): string = - var contact = self.getContactByID(id) - contact.systemTags.delete(contact.systemTags.find(contactBlocked)) - discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, contact.identityImage.thumbnail, contact.systemTags, contact.localNickname) - self.events.emit("contactUnblocked", Args()) - -proc getAllContacts*(): seq[Profile] = - result = map(status_contacts.getContacts().getElems(), proc(x: JsonNode): Profile = x.toProfileModel()) - -proc getAddedContacts*(): seq[Profile] = - result = getAllContacts().filter(c => c.systemTags.contains(contactAdded)) - -proc getContacts*(self: ContactModel): seq[Profile] = - result = getAllContacts() - self.events.emit("contactUpdate", ContactUpdateArgs(contacts: result)) - -proc getOrCreateContact*(self: ContactModel, id: string): Profile = - result = self.getContactByID(id) - if result == nil: - let alias = status_accounts.generateAlias(id) - result = Profile( - id: id, - username: alias, - localNickname: "", - identicon: status_accounts.generateIdenticon(id), - alias: alias, - ensName: "", - ensVerified: false, - appearance: 0, - systemTags: @[] - ) - -proc setNickName*(self: ContactModel, id: string, localNickname: string): string = - var contact = self.getOrCreateContact(id) - let nickname = - if (localNickname == ""): - contact.localNickname - elif (localNickname == DELETE_CONTACT): - "" - else: - localNickname - - var thumbnail = "" - if contact.identityImage != nil: - thumbnail = contact.identityImage.thumbnail - result = status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, nickname) - self.events.emit("contactAdded", Args()) - discard requestContactUpdate(contact.id) - - -proc addContact*(self: ContactModel, id: string): string = - var contact = self.getOrCreateContact(id) - - let updating = contact.systemTags.contains(contactAdded) - if not updating: - contact.systemTags.add(contactAdded) - discard status_chat.createProfileChat(contact.id) - else: - let index = contact.systemTags.find(contactBlocked) - if (index > -1): - contact.systemTags.delete(index) - - var thumbnail = "" - if contact.identityImage != nil: - thumbnail = contact.identityImage.thumbnail - - result = status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname) - self.events.emit("contactAdded", Args()) - discard requestContactUpdate(contact.id) - - if updating: - let profile = Profile( - id: contact.id, - username: contact.alias, - identicon: contact.identicon, - alias: contact.alias, - ensName: contact.ensName, - ensVerified: contact.ensVerified, - appearance: 0, - systemTags: contact.systemTags, - localNickname: contact.localNickname - ) - self.events.emit("contactUpdate", ContactUpdateArgs(contacts: @[profile])) - -proc removeContact*(self: ContactModel, id: string) = - let contact = self.getContactByID(id) - contact.systemTags.delete(contact.systemTags.find(contactAdded)) - - var thumbnail = "" - if contact.identityImage != nil: - thumbnail = contact.identityImage.thumbnail - - discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname) - self.events.emit("contactRemoved", Args()) - -proc isAdded*(self: ContactModel, id: string): bool = - var contact = self.getContactByID(id) - if contact.isNil: return false - contact.systemTags.contains(contactAdded) - -proc contactRequestReceived*(self: ContactModel, id: string): bool = - var contact = self.getContactByID(id) - if contact.isNil: return false - contact.systemTags.contains(contactRequest) - -proc rejectContactRequest*(self: ContactModel, id: string) = - let contact = self.getContactByID(id) - contact.systemTags.delete(contact.systemTags.find(contactRequest)) - - var thumbnail = "" - if contact.identityImage != nil: - thumbnail = contact.identityImage.thumbnail - - discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname) - self.events.emit("contactRemoved", Args()) diff --git a/src/status/devices.nim b/src/status/devices.nim deleted file mode 100644 index 329c611a37..0000000000 --- a/src/status/devices.nim +++ /dev/null @@ -1,43 +0,0 @@ -import system -import libstatus/settings -import types/[setting, installation] -import libstatus/installations -import json - -proc setDeviceName*(name: string) = - discard setInstallationMetadata(getSetting[string](Setting.InstallationId, "", true), name, hostOs) - -proc isDeviceSetup*():bool = - let installationId = getSetting[string](Setting.InstallationId, "", true) - let responseResult = getOurInstallations() - if responseResult.kind == JNull: - return false - for installation in responseResult: - if installation["id"].getStr == installationId: - return installation["metadata"].kind != JNull - result = false - -proc syncAllDevices*() = - let preferredUsername = getSetting[string](Setting.PreferredUsername, "") - discard syncDevices(preferredUsername) - -proc advertise*() = - discard sendPairInstallation() - -proc getAllDevices*():seq[Installation] = - let responseResult = getOurInstallations() - let installationId = getSetting[string](Setting.InstallationId, "", true) - result = @[] - if responseResult.kind != JNull: - for inst in responseResult: - var device = inst.toInstallation - if device.installationId == installationId: - device.isUserDevice = true - result.add(device) - -proc enable*(installationId: string) = - # TODO handle errors - discard enableInstallation(installationId) - -proc disable*(installationId: string) = - discard disableInstallation(installationId) diff --git a/src/status/ens.nim b/src/status/ens.nim deleted file mode 100644 index b3c1c43b1c..0000000000 --- a/src/status/ens.nim +++ /dev/null @@ -1,387 +0,0 @@ -import sequtils -import strutils -import profile/profile -import nimcrypto -import json -import json_serialization -import tables -import strformat -import libstatus/core -import ./types/[transaction, setting, rpc_response] -import utils -import libstatus/wallet -import stew/byteutils -import unicode -import transactions -import algorithm -import web3/[ethtypes, conversions], stew/byteutils, stint -import libstatus/eth/contracts -import libstatus/eth/transactions as eth_transactions -import chronicles, libp2p/[multihash, multicodec, cid] - -import ./settings as status_settings -import ./wallet as status_wallet - -const domain* = ".stateofus.eth" - -proc userName*(ensName: string, removeSuffix: bool = false): string = - if ensName != "" and ensName.endsWith(domain): - if removeSuffix: - result = ensName.split(".")[0] - else: - result = ensName - else: - if ensName.endsWith(".eth") and removeSuffix: - return ensName.split(".")[0] - result = ensName - -proc addDomain*(username: string): string = - if username.endsWith(".eth"): - return username - else: - return username & domain - -proc hasNickname*(contact: Profile): bool = contact.localNickname != "" - -proc userNameOrAlias*(contact: Profile, removeSuffix: bool = false): string = - if(contact.ensName != "" and contact.ensVerified): - result = "@" & userName(contact.ensName, removeSuffix) - elif(contact.localNickname != ""): - result = contact.localNickname - else: - result = contact.alias - -proc label*(username:string): string = - let name = username.toLower() - var node:array[32, byte] = keccak_256.digest(username).data - result = "0x" & node.toHex() - -proc namehash*(ensName:string): string = - let name = ensName.toLower() - var node:array[32, byte] - - node.fill(0) - var parts = name.split(".") - for i in countdown(parts.len - 1,0): - let elem = keccak_256.digest(parts[i]).data - var concatArrays: array[64, byte] - concatArrays[0..31] = node - concatArrays[32..63] = elem - node = keccak_256.digest(concatArrays).data - - result = "0x" & node.toHex() - -const registry* = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" -const resolver_signature = "0x0178b8bf" -proc resolver*(usernameHash: string): string = - let payload = %* [{ - "to": registry, - "from": "0x0000000000000000000000000000000000000000", - "data": fmt"{resolver_signature}{userNameHash}" - }, "latest"] - let response = callPrivateRPC("eth_call", payload) - # TODO: error handling - var resolverAddr = response.parseJson["result"].getStr - resolverAddr.removePrefix("0x000000000000000000000000") - result = "0x" & resolverAddr - -const owner_signature = "0x02571be3" # owner(bytes32 node) -proc owner*(username: string): string = - var userNameHash = namehash(addDomain(username)) - userNameHash.removePrefix("0x") - let payload = %* [{ - "to": registry, - "from": "0x0000000000000000000000000000000000000000", - "data": fmt"{owner_signature}{userNameHash}" - }, "latest"] - let response = callPrivateRPC("eth_call", payload) - # TODO: error handling - let ownerAddr = response.parseJson["result"].getStr; - if ownerAddr == "0x0000000000000000000000000000000000000000000000000000000000000000": - return "" - result = "0x" & ownerAddr.substr(26) - -const pubkey_signature = "0xc8690233" # pubkey(bytes32 node) -proc pubkey*(username: string): string = - var userNameHash = namehash(addDomain(username)) - userNameHash.removePrefix("0x") - let ensResolver = resolver(userNameHash) - let payload = %* [{ - "to": ensResolver, - "from": "0x0000000000000000000000000000000000000000", - "data": fmt"{pubkey_signature}{userNameHash}" - }, "latest"] - let response = callPrivateRPC("eth_call", payload) - # TODO: error handling - var pubkey = response.parseJson["result"].getStr - if pubkey == "0x" or pubkey == "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": - result = "" - else: - pubkey.removePrefix("0x") - result = "0x04" & pubkey - -const address_signature = "0x3b3b57de" # addr(bytes32 node) -proc address*(username: string): string = - var userNameHash = namehash(addDomain(username)) - userNameHash.removePrefix("0x") - let ensResolver = resolver(userNameHash) - let payload = %* [{ - "to": ensResolver, - "from": "0x0000000000000000000000000000000000000000", - "data": fmt"{address_signature}{userNameHash}" - }, "latest"] - let response = callPrivateRPC("eth_call", payload) - # TODO: error handling - let address = response.parseJson["result"].getStr; - if address == "0x0000000000000000000000000000000000000000000000000000000000000000": - return "" - result = "0x" & address.substr(26) - -const contenthash_signature = "0xbc1c58d1" # contenthash(bytes32) -proc contenthash*(ensAddr: string): string = - var ensHash = namehash(ensAddr) - ensHash.removePrefix("0x") - let ensResolver = resolver(ensHash) - let payload = %* [{ - "to": ensResolver, - "from": "0x0000000000000000000000000000000000000000", - "data": fmt"{contenthash_signature}{ensHash}" - }, "latest"] - - let response = callPrivateRPC("eth_call", payload) - let bytesResponse = response.parseJson["result"].getStr; - if bytesResponse == "0x": - return "" - - let size = fromHex(Stuint[256], bytesResponse[66..129]).truncate(int) - result = bytesResponse[130..129+size*2] - - -proc getPrice*(): Stuint[256] = - let - contract = contracts.getContract("ens-usernames") - payload = %* [{ - "to": $contract.address, - "data": contract.methods["getPrice"].encodeAbi() - }, "latest"] - - let responseStr = callPrivateRPC("eth_call", payload) - let response = Json.decode(responseStr, RpcResponse) - if not response.error.isNil: - raise newException(RpcException, "Error getting ens username price: " & response.error.message) - if response.result == "0x": - raise newException(RpcException, "Error getting ens username price: 0x") - result = fromHex(Stuint[256], response.result) - -proc releaseEstimateGas*(username: string, address: string, success: var bool): int = - let - label = fromHex(FixedBytes[32], label(username)) - ensUsernamesContract = contracts.getContract("ens-usernames") - release = Release(label: label) - - var tx = transactions.buildTokenTransaction(parseAddress(address), ensUsernamesContract.address, "", "") - try: - let response = ensUsernamesContract.methods["release"].estimateGas(tx, release, success) - if success: - result = fromHex[int](response) - except RpcException as e: - error "Could not estimate gas for ens release", err=e.msg - -proc release*(username: string, address: string, gas, gasPrice, password: string, success: var bool): string = - let - label = fromHex(FixedBytes[32], label(username)) - ensUsernamesContract = contracts.getContract("ens-usernames") - release = Release(label: label) - - var tx = transactions.buildTokenTransaction(parseAddress(address), ensUsernamesContract.address, "", "") - try: - result = ensUsernamesContract.methods["release"].send(tx, release, password, success) - if success: - trackPendingTransaction(result, address, $ensUsernamesContract.address, PendingTransactionType.ReleaseENS, username) - except RpcException as e: - error "Could not estimate gas for ens release", err=e.msg - -proc getExpirationTime*(username: string, success: var bool): int = - let - label = fromHex(FixedBytes[32], label(username)) - expTime = ExpirationTime(label: label) - ensUsernamesContract = contracts.getContract("ens-usernames") - - var tx = transactions.buildTransaction(parseAddress("0x0000000000000000000000000000000000000000"), 0.u256) - tx.to = ensUsernamesContract.address.some - tx.data = ensUsernamesContract.methods["getExpirationTime"].encodeAbi(expTime) - var response = "" - try: - response = eth_transactions.call(tx).result - success = true - except RpcException as e: - success = false - error "Error obtaining expiration time", err=e.msg - - if success: - result = fromHex[int](response) - -proc extractCoordinates*(pubkey: string):tuple[x: string, y:string] = - result = ("0x" & pubkey[4..67], "0x" & pubkey[68..131]) - -proc registerUsernameEstimateGas*(username: string, address: string, pubKey: string, success: var bool): int = - let - label = fromHex(FixedBytes[32], label(username)) - coordinates = extractCoordinates(pubkey) - x = fromHex(FixedBytes[32], coordinates.x) - y = fromHex(FixedBytes[32], coordinates.y) - ensUsernamesContract = contracts.getContract("ens-usernames") - sntContract = contracts.getSntContract() - price = getPrice() - - let - register = Register(label: label, account: parseAddress(address), x: x, y: y) - registerAbiEncoded = ensUsernamesContract.methods["register"].encodeAbi(register) - approveAndCallObj = ApproveAndCall[132](to: ensUsernamesContract.address, value: price, data: DynamicBytes[132].fromHex(registerAbiEncoded)) - approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(approveAndCallObj) - - var tx = transactions.buildTokenTransaction(parseAddress(address), sntContract.address, "", "") - - let response = sntContract.methods["approveAndCall"].estimateGas(tx, approveAndCallObj, success) - if success: - result = fromHex[int](response) - -proc registerUsername*(username, pubKey, address, gas, gasPrice, password: string, success: var bool): string = - let - label = fromHex(FixedBytes[32], label(username)) - coordinates = extractCoordinates(pubkey) - x = fromHex(FixedBytes[32], coordinates.x) - y = fromHex(FixedBytes[32], coordinates.y) - ensUsernamesContract = contracts.getContract("ens-usernames") - sntContract = contracts.getSntContract() - price = getPrice() - - let - register = Register(label: label, account: parseAddress(address), x: x, y: y) - registerAbiEncoded = ensUsernamesContract.methods["register"].encodeAbi(register) - approveAndCallObj = ApproveAndCall[132](to: ensUsernamesContract.address, value: price, data: DynamicBytes[132].fromHex(registerAbiEncoded)) - - var tx = transactions.buildTokenTransaction(parseAddress(address), sntContract.address, gas, gasPrice) - - result = sntContract.methods["approveAndCall"].send(tx, approveAndCallObj, password, success) - if success: - trackPendingTransaction(result, address, $sntContract.address, PendingTransactionType.RegisterENS, username & domain) - -proc setPubKeyEstimateGas*(username: string, address: string, pubKey: string, success: var bool): int = - var hash = namehash(username) - hash.removePrefix("0x") - - let - label = fromHex(FixedBytes[32], "0x" & hash) - x = fromHex(FixedBytes[32], "0x" & pubkey[4..67]) - y = fromHex(FixedBytes[32], "0x" & pubkey[68..131]) - resolverContract = contracts.getContract("ens-resolver") - setPubkey = SetPubkey(label: label, x: x, y: y) - resolverAddress = resolver(hash) - - var tx = transactions.buildTokenTransaction(parseAddress(address), parseAddress(resolverAddress), "", "") - - try: - let response = resolverContract.methods["setPubkey"].estimateGas(tx, setPubkey, success) - if success: - result = fromHex[int](response) - except RpcException as e: - raise - -proc setPubKey*(username, pubKey, address, gas, gasPrice, password: string, success: var bool): string = - var hash = namehash(username) - hash.removePrefix("0x") - - let - label = fromHex(FixedBytes[32], "0x" & hash) - x = fromHex(FixedBytes[32], "0x" & pubkey[4..67]) - y = fromHex(FixedBytes[32], "0x" & pubkey[68..131]) - resolverContract = contracts.getContract("ens-resolver") - setPubkey = SetPubkey(label: label, x: x, y: y) - resolverAddress = resolver(hash) - - var tx = transactions.buildTokenTransaction(parseAddress(address), parseAddress(resolverAddress), gas, gasPrice) - - try: - result = resolverContract.methods["setPubkey"].send(tx, setPubkey, password, success) - if success: - trackPendingTransaction(result, $address, resolverAddress, PendingTransactionType.SetPubKey, username) - except RpcException as e: - raise - -proc statusRegistrarAddress*():string = - result = $contracts.getContract("ens-usernames").address - - -type - ENSType* {.pure.} = enum - IPFS, - SWARM, - IPNS, - UNKNOWN - -proc decodeENSContentHash*(value: string): tuple[ensType: ENSType, output: string] = - if value == "": - return (ENSType.UNKNOWN, "") - - if value[0..5] == "e40101": - return (ENSType.SWARM, value.split("1b20")[1]) - - if value[0..7] == "e3010170": - try: - let defaultCodec = parseHexInt("70") #dag-pb - var codec = defaultCodec # no codec specified - var codecStartIdx = 2 # idx of where codec would start if it was specified - # handle the case when starts with 0xe30170 instead of 0xe3010170 - if value[2..5] == "0101": - codecStartIdx = 6 - codec = parseHexInt(value[6..7]) - elif value[2..3] == "01" and value[4..5] != "12": - codecStartIdx = 4 - codec = parseHexInt(value[4..5]) - - # strip the info we no longer need - var multiHashStr = value[codecStartIdx + 2.. 0: - result = "already-connected" - else: - let ownerAddr = owner(username) - if ownerAddr == "" and isStatus: - result = "available" - else: - let userPubKey = status_settings.getSetting2[string](Setting.PublicKey, "0x0") - let userWallet = status_wallet.getWalletAccounts()[0].address - let ens_pubkey = pubkey(ens) - if ownerAddr != "": - if ens_pubkey == "" and ownerAddr == userWallet: - result = "owned" # "Continuing will connect this username with your chat key." - elif ens_pubkey == userPubkey: - result = "connected" - elif ownerAddr == userWallet: - result = "connected-different-key" # "Continuing will require a transaction to connect the username with your current chat key.", - else: - result = "taken" - else: - result = "taken" diff --git a/src/status/fleet.nim b/src/status/fleet.nim deleted file mode 100644 index 3b19ac9b95..0000000000 --- a/src/status/fleet.nim +++ /dev/null @@ -1,15 +0,0 @@ -import ./types/[fleet] - -export fleet - -type - FleetModel* = ref object - config*: FleetConfig - -proc newFleetModel*(fleetConfigJson: string): FleetModel = - result = FleetModel() - result.config = fleetConfigJson.toFleetConfig() - -proc delete*(self: FleetModel) = - discard - diff --git a/src/status/gif.nim b/src/status/gif.nim deleted file mode 100644 index 794f6f2a0a..0000000000 --- a/src/status/gif.nim +++ /dev/null @@ -1,151 +0,0 @@ -import httpclient -import json -import strformat -import os -import sequtils - -from libstatus/gif import getRecentGifs, getFavoriteGifs, setFavoriteGifs, setRecentGifs - - -const MAX_RECENT = 50 -# set via `nim c` param `-d:TENOR_API_KEY:[api_key]`; should be set in CI/release builds -const TENOR_API_KEY {.strdefine.} = "" -let TENOR_API_KEY_ENV = $getEnv("TENOR_API_KEY") - -let TENOR_API_KEY_RESOLVED = - if TENOR_API_KEY_ENV != "": - TENOR_API_KEY_ENV - else: - TENOR_API_KEY - -const baseUrl = "https://g.tenor.com/v1/" -let defaultParams = fmt("&media_filter=minimal&limit=50&key={TENOR_API_KEY_RESOLVED}") - -type - GifItem* = object - id*: string - title*: string - url*: string - tinyUrl*: string - height*: int - -proc tenorToGifItem(jsonMsg: JsonNode): GifItem = - return GifItem( - id: jsonMsg{"id"}.getStr, - title: jsonMsg{"title"}.getStr, - url: jsonMsg{"media"}[0]["gif"]["url"].getStr, - tinyUrl: jsonMsg{"media"}[0]["tinygif"]["url"].getStr, - height: jsonMsg{"media"}[0]["gif"]["dims"][1].getInt - ) - -proc settingToGifItem(jsonMsg: JsonNode): GifItem = - return GifItem( - id: jsonMsg{"id"}.getStr, - title: jsonMsg{"title"}.getStr, - url: jsonMsg{"url"}.getStr, - tinyUrl: jsonMsg{"tinyUrl"}.getStr, - height: jsonMsg{"height"}.getInt - ) - -proc toJsonNode*(self: GifItem): JsonNode = - result = %* { - "id": self.id, - "title": self.title, - "url": self.url, - "tinyUrl": self.tinyUrl, - "height": self.height - } - -proc `$`*(self: GifItem): string = - return fmt"GifItem(id:{self.id}, title:{self.title}, url:{self.url}, tinyUrl:{self.tinyUrl}, height:{self.height})" - -type - GifClient* = ref object - client: HttpClient - favorites: seq[GifItem] - recents: seq[GifItem] - favoritesLoaded: bool - recentsLoaded: bool - -proc newGifClient*(): GifClient = - result = GifClient() - result.client = newHttpClient() - result.favorites = @[] - result.recents = @[] - -proc tenorQuery(self: GifClient, path: string): seq[GifItem] = - try: - let content = self.client.getContent(fmt("{baseUrl}{path}{defaultParams}")) - let doc = content.parseJson() - - var items: seq[GifItem] = @[] - for json in doc["results"]: - items.add(tenorToGifItem(json)) - - return items - except: - echo getCurrentExceptionMsg() - return @[] - -proc search*(self: GifClient, query: string): seq[GifItem] = - return self.tenorQuery(fmt("search?q={query}")) - -proc getTrendings*(self: GifClient): seq[GifItem] = - return self.tenorQuery("trending?") - -proc getFavorites*(self: GifClient): seq[GifItem] = - if not self.favoritesLoaded: - self.favoritesLoaded = true - self.favorites = map(getFavoriteGifs(){"items"}.getElems(), settingToGifItem) - - return self.favorites - -proc getRecents*(self: GifClient): seq[GifItem] = - if not self.recentsLoaded: - self.recentsLoaded = true - self.recents = map(getRecentGifs(){"items"}.getElems(), settingToGifItem) - - return self.recents - -proc isFavorite*(self: GifClient, gifItem: GifItem): bool = - for favorite in self.getFavorites(): - if favorite.id == gifItem.id: - return true - - return false - -proc toggleFavorite*(self: GifClient, gifItem: GifItem) = - var newFavorites: seq[GifItem] = @[] - var found = false - - for favoriteGif in self.getFavorites(): - if favoriteGif.id == gifItem.id: - found = true - continue - - newFavorites.add(favoriteGif) - - if not found: - newFavorites.add(gifItem) - - self.favorites = newFavorites - setFavoriteGifs(%*{"items": map(newFavorites, toJsonNode)}) - -proc addToRecents*(self: GifClient, gifItem: GifItem) = - let recents = self.getRecents() - var newRecents: seq[GifItem] = @[gifItem] - var idx = 0 - - while idx < MAX_RECENT - 1: - if idx >= recents.len: - break - - if recents[idx].id == gifItem.id: - idx += 1 - continue - - newRecents.add(recents[idx]) - idx += 1 - - self.recents = newRecents - setRecentGifs(%*{"items": map(newRecents, toJsonNode)}) \ No newline at end of file diff --git a/src/status/libstatus/accounts.nim b/src/status/libstatus/accounts.nim deleted file mode 100644 index 175da681e4..0000000000 --- a/src/status/libstatus/accounts.nim +++ /dev/null @@ -1,393 +0,0 @@ -import json, os, nimcrypto, uuids, json_serialization, chronicles, strutils - -from status_go import multiAccountGenerateAndDeriveAddresses, generateAlias, identicon, saveAccountAndLogin, login, openAccounts, getNodeConfig -import core -import ../utils as utils -import ../types/[account, fleet, rpc_response] -import ../../app_service/signals/[base] -import accounts/constants - -proc getNetworkConfig(currentNetwork: string): JsonNode = - result = constants.DEFAULT_NETWORKS.first("id", currentNetwork) - - -proc getDefaultNodeConfig*(fleetConfig: FleetConfig, installationId: string): JsonNode = - let networkConfig = getNetworkConfig(constants.DEFAULT_NETWORK_NAME) - let upstreamUrl = networkConfig["config"]["UpstreamConfig"]["URL"] - let fleet = Fleet.PROD - - var newDataDir = networkConfig["config"]["DataDir"].getStr - newDataDir.removeSuffix("_rpc") - result = constants.NODE_CONFIG.copy() - result["ClusterConfig"]["Fleet"] = newJString($fleet) - result["ClusterConfig"]["BootNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Bootnodes) - result["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers) - result["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper) - result["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous) - result["ClusterConfig"]["WakuNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku) - result["ClusterConfig"]["WakuStoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku) - result["NetworkId"] = networkConfig["config"]["NetworkId"] - result["DataDir"] = newDataDir.newJString() - result["UpstreamConfig"]["Enabled"] = networkConfig["config"]["UpstreamConfig"]["Enabled"] - result["UpstreamConfig"]["URL"] = upstreamUrl - result["ShhextConfig"]["InstallationID"] = newJString(installationId) - - # TODO: commented since it's not necessary (we do the connections thru C bindings). Enable it thru an option once status-nodes are able to be configured in desktop - # result["ListenAddr"] = if existsEnv("STATUS_PORT"): newJString("0.0.0.0:" & $getEnv("STATUS_PORT")) else: newJString("0.0.0.0:30305") - - -proc hashPassword*(password: string): string = - result = "0x" & $keccak_256.digest(password) - -proc getDefaultAccount*(): string = - var response = callPrivateRPC("eth_accounts") - result = parseJson(response)["result"][0].getStr() - -proc generateAddresses*(n = 5): seq[GeneratedAccount] = - let multiAccountConfig = %* { - "n": n, - "mnemonicPhraseLength": 12, - "bip39Passphrase": "", - "paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET] - } - let generatedAccounts = $status_go.multiAccountGenerateAndDeriveAddresses($multiAccountConfig) - result = Json.decode(generatedAccounts, seq[GeneratedAccount]) - -proc generateAlias*(publicKey: string): string = - result = $status_go.generateAlias(publicKey) - -proc generateIdenticon*(publicKey: string): string = - result = $status_go.identicon(publicKey) - -proc initNode*() = - createDir(STATUSGODIR) - createDir(KEYSTOREDIR) - discard $status_go.initKeystore(KEYSTOREDIR) - -proc parseIdentityImage*(images: JsonNode): IdentityImage = - result = IdentityImage() - if (images.kind != JNull): - for image in images: - if (image["type"].getStr == "thumbnail"): - # TODO check if this can be url or if it's always uri - result.thumbnail = image["uri"].getStr - elif (image["type"].getStr == "large"): - result.large = image["uri"].getStr - -proc openAccounts*(): seq[NodeAccount] = - let strNodeAccounts = status_go.openAccounts(STATUSGODIR).parseJson - # FIXME fix serialization - result = @[] - if (strNodeAccounts.kind != JNull): - for account in strNodeAccounts: - let nodeAccount = NodeAccount( - name: account["name"].getStr, - timestamp: account["timestamp"].getInt, - keyUid: account["key-uid"].getStr, - identicon: account["identicon"].getStr, - keycardPairing: account["keycard-pairing"].getStr - ) - if (account{"images"}.kind != JNull): - nodeAccount.identityImage = parseIdentityImage(account["images"]) - - result.add(nodeAccount) - - -proc saveAccountAndLogin*( - account: GeneratedAccount, - accountData: string, - password: string, - configJSON: string, - settingsJSON: string): Account = - let hashedPassword = hashPassword(password) - let subaccountData = %* [ - { - "public-key": account.derived.defaultWallet.publicKey, - "address": account.derived.defaultWallet.address, - "color": "#4360df", - "wallet": true, - "path": constants.PATH_DEFAULT_WALLET, - "name": "Status account" - }, - { - "public-key": account.derived.whisper.publicKey, - "address": account.derived.whisper.address, - "name": account.name, - "identicon": account.identicon, - "path": constants.PATH_WHISPER, - "chat": true - } - ] - - var savedResult = $status_go.saveAccountAndLogin(accountData, hashedPassword, settingsJSON, configJSON, $subaccountData) - let parsedSavedResult = savedResult.parseJson - let error = parsedSavedResult["error"].getStr - - if error == "": - debug "Account saved succesfully" - result = account.toAccount - return - - raise newException(StatusGoException, "Error saving account and logging in: " & error) - -proc storeDerivedAccounts*(account: GeneratedAccount, password: string, paths: seq[string] = @[PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET]): MultiAccounts = - let hashedPassword = hashPassword(password) - let multiAccount = %* { - "accountID": account.id, - "paths": paths, - "password": hashedPassword - } - let response = $status_go.multiAccountStoreDerivedAccounts($multiAccount); - - try: - result = Json.decode($response, MultiAccounts) - except: - let err = Json.decode($response, StatusGoError) - raise newException(StatusGoException, "Error storing multiaccount derived accounts: " & err.error) - -proc getAccountData*(account: GeneratedAccount): JsonNode = - result = %* { - "name": account.name, - "address": account.address, - "identicon": account.identicon, - "key-uid": account.keyUid, - "keycard-pairing": nil - } - -proc getAccountSettings*(account: GeneratedAccount, defaultNetworks: JsonNode, installationId: string): JsonNode = - result = %* { - "key-uid": account.keyUid, - "mnemonic": account.mnemonic, - "public-key": account.derived.whisper.publicKey, - "name": account.name, - "address": account.address, - "eip1581-address": account.derived.eip1581.address, - "dapps-address": account.derived.defaultWallet.address, - "wallet-root-address": account.derived.walletRoot.address, - "preview-privacy?": true, - "signing-phrase": generateSigningPhrase(3), - "log-level": "INFO", - "latest-derived-path": 0, - "networks/networks": defaultNetworks, - "currency": "usd", - "identicon": account.identicon, - "waku-enabled": true, - "wallet/visible-tokens": { - "mainnet": ["SNT"] - }, - "appearance": 0, - "networks/current-network": constants.DEFAULT_NETWORK_NAME, - "installation-id": installationId - } - -proc setupAccount*(fleetConfig: FleetConfig, account: GeneratedAccount, password: string): Account = - try: - let storeDerivedResult = storeDerivedAccounts(account, password) - let accountData = getAccountData(account) - let installationId = $genUUID() - var settingsJSON = getAccountSettings(account, constants.DEFAULT_NETWORKS, installationId) - var nodeConfig = getDefaultNodeConfig(fleetConfig, installationId) - result = saveAccountAndLogin(account, $accountData, password, $nodeConfig, $settingsJSON) - - except StatusGoException as e: - raise newException(StatusGoException, "Error setting up account: " & e.msg) - - finally: - # TODO this is needed for now for the retrieving of past messages. We'll either move or remove it later - let peer = "enode://44160e22e8b42bd32a06c1532165fa9e096eebedd7fa6d6e5f8bbef0440bc4a4591fe3651be68193a7ec029021cdb496cfe1d7f9f1dc69eb99226e6f39a7a5d4@35.225.221.245:443" - discard status_go.addPeer(peer) - -proc login*(nodeAccount: NodeAccount, password: string): NodeAccount = - let hashedPassword = hashPassword(password) - let account = nodeAccount.toAccount - let loginResult = $status_go.login($toJson(account), hashedPassword) - let error = parseJson(loginResult)["error"].getStr - - if error == "": - debug "Login requested", user=nodeAccount.name - result = nodeAccount - return - - raise newException(StatusGoException, "Error logging in: " & error) - -proc loadAccount*(address: string, password: string): GeneratedAccount = - let hashedPassword = hashPassword(password) - let inputJson = %* { - "address": address, - "password": hashedPassword - } - let loadResult = $status_go.multiAccountLoadAccount($inputJson) - let parsedLoadResult = loadResult.parseJson - let error = parsedLoadResult{"error"}.getStr - - if error == "": - debug "Account loaded succesfully" - result = Json.decode(loadResult, GeneratedAccount) - return - - raise newException(StatusGoException, "Error loading wallet account: " & error) - -proc verifyAccountPassword*(address: string, password: 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 changeDatabasePassword*(keyUID: string, password: string, newPassword: string): bool = - let hashedPassword = hashPassword(password) - let hashedNewPassword = hashPassword(newPassword) - let changeResult = $status_go.changeDatabasePassword(keyUID, hashedPassword, hashedNewPassword) - let error = parseJson(changeResult)["error"].getStr - return error == "" - -proc multiAccountImportMnemonic*(mnemonic: string): GeneratedAccount = - let mnemonicJson = %* { - "mnemonicPhrase": mnemonic, - "Bip39Passphrase": "" - } - # status_go.multiAccountImportMnemonic never results in an error given ANY input - let importResult = $status_go.multiAccountImportMnemonic($mnemonicJson) - result = Json.decode(importResult, GeneratedAccount) - -proc MultiAccountImportPrivateKey*(privateKey: string): GeneratedAccount = - let privateKeyJson = %* { - "privateKey": privateKey - } - # status_go.MultiAccountImportPrivateKey never results in an error given ANY input - try: - let importResult = $status_go.multiAccountImportPrivateKey($privateKeyJson) - result = Json.decode(importResult, GeneratedAccount) - except Exception as e: - error "Error getting account from private key", msg=e.msg - - -proc storeDerivedWallet*(account: GeneratedAccount, password: string, walletIndex: int, accountType: string): string = - let hashedPassword = hashPassword(password) - let derivationPath = (if accountType == constants.GENERATED: "m/" else: "m/44'/60'/0'/0/") & $walletIndex - let multiAccount = %* { - "accountID": account.id, - "paths": [derivationPath], - "password": hashedPassword - } - let response = parseJson($status_go.multiAccountStoreDerivedAccounts($multiAccount)); - let error = response{"error"}.getStr - if error == "": - debug "Wallet stored succesfully" - return "m/44'/60'/0'/0/" & $walletIndex - raise newException(StatusGoException, error) - -proc storePrivateKeyAccount*(account: GeneratedAccount, password: string) = - let hashedPassword = hashPassword(password) - let response = parseJson($status_go.multiAccountStoreAccount($(%*{"accountID": account.id, "password": hashedPassword}))); - let error = response{"error"}.getStr - if error == "": - debug "Wallet stored succesfully" - return - - raise newException(StatusGoException, error) - -proc saveAccount*(account: GeneratedAccount, password: string, color: string, accountType: string, isADerivedAccount = true, walletIndex: int = 0 ): DerivedAccount = - try: - var derivationPath = "m/44'/60'/0'/0/0" - if (isADerivedAccount): - # Only store derived accounts. Private key accounts are not multiaccounts - derivationPath = storeDerivedWallet(account, password, walletIndex, accountType) - elif accountType == constants.KEY: - storePrivateKeyAccount(account, password) - - var address = account.derived.defaultWallet.address - var publicKey = account.derived.defaultWallet.publicKey - - if (address == ""): - address = account.address - publicKey = account.publicKey - - echo callPrivateRPC("accounts_saveAccounts", %* [ - [{ - "color": color, - "name": account.name, - "address": address, - "public-key": publicKey, - "type": accountType, - "path": derivationPath - }] - ]) - - result = DerivedAccount(address: address, publicKey: publicKey, derivationPath: derivationPath) - except: - error "Error storing the new account. Bad password?" - raise - -proc changeAccount*(name, address, publicKey, walletType, iconColor: string): string = - try: - let response = callPrivateRPC("accounts_saveAccounts", %* [ - [{ - "color": iconColor, - "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 - }] - ]) - - utils.handleRPCErrors(response) - return "" - except Exception as e: - error "Error saving the account", msg=e.msg - result = e.msg - -proc deleteAccount*(address: string): string = - try: - let response = callPrivateRPC("accounts_deleteAccount", %* [address]) - - utils.handleRPCErrors(response) - return "" - except Exception as e: - error "Error removing the account", msg=e.msg - result = e.msg - -proc deriveWallet*(accountId: string, walletIndex: int): DerivedAccount = - let path = "m/" & $walletIndex - let deriveJson = %* { - "accountID": accountId, - "paths": [path] - } - let deriveResult = parseJson($status_go.multiAccountDeriveAddresses($deriveJson)) - result = DerivedAccount( - address: deriveResult[path]["address"].getStr, - publicKey: deriveResult[path]["publicKey"].getStr) - -proc deriveAccounts*(accountId: string): MultiAccounts = - let deriveJson = %* { - "accountID": accountId, - "paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET] - } - let deriveResult = $status_go.multiAccountDeriveAddresses($deriveJson) - result = Json.decode(deriveResult, MultiAccounts) - -proc logout*(): StatusGoError = - result = Json.decode($status_go.logout(), StatusGoError) - -proc storeIdentityImage*(keyUID: string, imagePath: string, aX, aY, bX, bY: int): IdentityImage = - let response = callPrivateRPC("multiaccounts_storeIdentityImage", %* [keyUID, imagePath, aX, aY, bX, bY]).parseJson - result = parseIdentityImage(response{"result"}) - -proc getIdentityImage*(keyUID: string): IdentityImage = - try: - let response = callPrivateRPC("multiaccounts_getIdentityImages", %* [keyUID]).parseJson - result = parseIdentityImage(response{"result"}) - except Exception as e: - error "Error getting identity image", msg=e.msg - -proc deleteIdentityImage*(keyUID: string): string = - try: - let response = callPrivateRPC("multiaccounts_deleteIdentityImage", %* [keyUID]).parseJson - result = "" - except Exception as e: - error "Error getting identity image", msg=e.msg - result = e.msg diff --git a/src/status/libstatus/accounts/constants.nim b/src/status/libstatus/accounts/constants.nim deleted file mode 100644 index c52a2c6a3a..0000000000 --- a/src/status/libstatus/accounts/constants.nim +++ /dev/null @@ -1,235 +0,0 @@ -import # std libs - json, os, sequtils, strutils - -import # vendor libs - confutils - -const GENERATED* = "generated" -const SEED* = "seed" -const KEY* = "key" -const WATCH* = "watch" - -const ZERO_ADDRESS* = "0x0000000000000000000000000000000000000000" - -const PATH_WALLET_ROOT* = "m/44'/60'/0'/0" -# EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived -const PATH_EIP_1581* = "m/43'/60'/1581'" -# BIP44-0 Wallet key, the default wallet key -const PATH_DEFAULT_WALLET* = PATH_WALLET_ROOT & "/0" -# EIP1581 Chat Key 0, the default whisper key -const PATH_WHISPER* = PATH_EIP_1581 & "/0'/0" - -# set via `nim c` param `-d:INFURA_TOKEN:[token]`; should be set in CI/release builds -const INFURA_TOKEN {.strdefine.} = "" -# allow runtime override via environment variable; core contributors can set a -# release token in this way for local development -let INFURA_TOKEN_ENV = $getEnv("INFURA_TOKEN") - -let INFURA_TOKEN_RESOLVED = - if INFURA_TOKEN_ENV != "": - INFURA_TOKEN_ENV - else: - INFURA_TOKEN - -let DEFAULT_NETWORKS* = %* [ - { - "id": "testnet_rpc", - "etherscan-link": "https://ropsten.etherscan.io/address/", - "name": "Ropsten with upstream RPC", - "config": { - "NetworkId": 3, - "DataDir": "/ethereum/testnet_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://ropsten.infura.io/v3/" & INFURA_TOKEN_RESOLVED - } - } - }, - { - "id": "rinkeby_rpc", - "etherscan-link": "https://rinkeby.etherscan.io/address/", - "name": "Rinkeby with upstream RPC", - "config": { - "NetworkId": 4, - "DataDir": "/ethereum/rinkeby_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED - } - } - }, - { - "id": "goerli_rpc", - "etherscan-link": "https://goerli.etherscan.io/address/", - "name": "Goerli with upstream RPC", - "config": { - "NetworkId": 5, - "DataDir": "/ethereum/goerli_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://goerli.blockscout.com/" - } - } - }, - { - "id": "mainnet_rpc", - "etherscan-link": "https://etherscan.io/address/", - "name": "Mainnet with upstream RPC", - "config": { - "NetworkId": 1, - "DataDir": "/ethereum/mainnet_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED - } - } - }, - { - "id": "xdai_rpc", - "name": "xDai Chain", - "config": { - "NetworkId": 100, - "DataDir": "/ethereum/xdai_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://dai.poa.network" - } - } - }, - { - "id": "poa_rpc", - "name": "POA Network", - "config": { - "NetworkId": 99, - "DataDir": "/ethereum/poa_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://core.poa.network" - } - } - } -] - -var NODE_CONFIG* = %* { - "BrowsersConfig": { - "Enabled": true - }, - "ClusterConfig": { - "Enabled": true - }, - "DataDir": "./ethereum/mainnet", - "EnableNTPSync": true, - "KeyStoreDir": "./keystore", - # TODO: commented since it's not necessary (we do the connections thru C bindings). Enable it thru an option once status-nodes are able to be configured in desktop - #"ListenAddr": ":30304", - "LogEnabled": true, - "LogFile": "geth.log", - "LogLevel": "INFO", - "MailserversConfig": { - "Enabled": true - }, - "Name": "StatusDesktop", - "NetworkId": 1, - "NoDiscovery": false, - "PermissionsConfig": { - "Enabled": true - }, - "Rendezvous": true, - "RegisterTopics": @["whispermail"], - "RequireTopics": { - "whisper": { - "Max": 2, - "Min": 2 - } - }, - "ShhextConfig": { - "BackupDisabledDataDir": "./", - "DataSyncEnabled": true, - "InstallationID": "aef27732-8d86-5039-a32e-bdbe094d8791", - "MailServerConfirmations": true, - "MaxMessageDeliveryAttempts": 6, - "PFSEnabled": true, - "VerifyENSContractAddress": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "VerifyENSURL": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED, - "VerifyTransactionChainID": 1, - "VerifyTransactionURL": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED - }, - "StatusAccountsConfig": { - "Enabled": true - }, - "UpstreamConfig": { - "Enabled": true, - "URL": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED - }, - "WakuConfig": { - "BloomFilterMode": true, - "Enabled": true, - "LightClient": true, - "MinimumPoW": 0.001 - }, - "WakuV2Config": { - "Enabled": false, - "Host": "0.0.0.0", - "Port": 0 - }, - "WalletConfig": { - "Enabled": true - } -} - -const DEFAULT_NETWORK_NAME* = "mainnet_rpc" - -const sep = when defined(windows): "\\" else: "/" - -proc defaultDataDir(): string = - let homeDir = getHomeDir() - let parentDir = - if defined(development): - parentDir(getAppDir()) - elif homeDir == "": - getCurrentDir() - elif defined(macosx): - joinPath(homeDir, "Library", "Application Support") - elif defined(windows): - let targetDir = getEnv("LOCALAPPDATA").string - if targetDir == "": - joinPath(homeDir, "AppData", "Local") - else: - targetDir - else: - let targetDir = getEnv("XDG_CONFIG_HOME").string - if targetDir == "": - joinPath(homeDir, ".config") - else: - targetDir - absolutePath(joinPath(parentDir, "Status")) - -type StatusDesktopConfig = object - dataDir* {. - defaultValue: defaultDataDir() - desc: "Status Desktop data directory" - abbr: "d" .}: string - -# On macOS the first time when a user gets the "App downloaded from the -# internet" warning, and clicks the Open button, the OS passes a unique process -# serial number (PSN) as -psn_... command-line argument, which we remove before -# processing the arguments with nim-confutils. -# Credit: https://github.com/bitcoin/bitcoin/blame/b6e34afe9735faf97d6be7a90fafd33ec18c0cbb/src/util/system.cpp#L383-L389 - -var cliParams = commandLineParams() -if defined(macosx): - cliParams.keepIf(proc(p: string): bool = not p.startsWith("-psn_")) - -let desktopConfig = StatusDesktopConfig.load(cliParams) - -let - baseDir = absolutePath(expandTilde(desktopConfig.dataDir)) - DATADIR* = baseDir & sep - STATUSGODIR* = joinPath(baseDir, "data") & sep - KEYSTOREDIR* = joinPath(baseDir, "data", "keystore") & sep - TMPDIR* = joinPath(baseDir, "tmp") & sep - LOGDIR* = joinPath(baseDir, "logs") & sep - -createDir(DATADIR) -createDir(TMPDIR) -createDir(LOGDIR) diff --git a/src/status/libstatus/accounts/signing_phrases.nim b/src/status/libstatus/accounts/signing_phrases.nim deleted file mode 100644 index e459823bf3..0000000000 --- a/src/status/libstatus/accounts/signing_phrases.nim +++ /dev/null @@ -1,623 +0,0 @@ -const phrases*: seq[string] = @[ - "acid", - "alto", - "apse", - "arch", - "area", - "army", - "atom", - "aunt", - "babe", - "baby", - "back", - "bail", - "bait", - "bake", - "ball", - "band", - "bank", - "barn", - "base", - "bass", - "bath", - "bead", - "beak", - "beam", - "bean", - "bear", - "beat", - "beef", - "beer", - "beet", - "bell", - "belt", - "bend", - "bike", - "bill", - "bird", - "bite", - "blow", - "blue", - "boar", - "boat", - "body", - "bolt", - "bomb", - "bone", - "book", - "boot", - "bore", - "boss", - "bowl", - "brow", - "bulb", - "bull", - "burn", - "bush", - "bust", - "cafe", - "cake", - "calf", - "call", - "calm", - "camp", - "cane", - "cape", - "card", - "care", - "carp", - "cart", - "case", - "cash", - "cast", - "cave", - "cell", - "cent", - "chap", - "chef", - "chin", - "chip", - "chop", - "chub", - "chug", - "city", - "clam", - "clef", - "clip", - "club", - "clue", - "coal", - "coat", - "code", - "coil", - "coin", - "coke", - "cold", - "colt", - "comb", - "cone", - "cook", - "cope", - "copy", - "cord", - "cork", - "corn", - "cost", - "crab", - "craw", - "crew", - "crib", - "crop", - "crow", - "curl", - "cyst", - "dame", - "dare", - "dark", - "dart", - "dash", - "data", - "date", - "dead", - "deal", - "dear", - "debt", - "deck", - "deep", - "deer", - "desk", - "dhow", - "diet", - "dill", - "dime", - "dirt", - "dish", - "disk", - "dock", - "doll", - "door", - "dory", - "drag", - "draw", - "drop", - "drug", - "drum", - "duck", - "dump", - "dust", - "duty", - "ease", - "east", - "eave", - "eddy", - "edge", - "envy", - "epee", - "exam", - "exit", - "face", - "fact", - "fail", - "fall", - "fame", - "fang", - "farm", - "fawn", - "fear", - "feed", - "feel", - "feet", - "file", - "fill", - "film", - "find", - "fine", - "fire", - "fish", - "flag", - "flat", - "flax", - "flow", - "foam", - "fold", - "font", - "food", - "foot", - "fork", - "form", - "fort", - "fowl", - "frog", - "fuel", - "full", - "gain", - "gale", - "galn", - "game", - "garb", - "gate", - "gear", - "gene", - "gift", - "girl", - "give", - "glad", - "glen", - "glue", - "glut", - "goal", - "goat", - "gold", - "golf", - "gong", - "good", - "gown", - "grab", - "gram", - "gray", - "grey", - "grip", - "grit", - "gyro", - "hail", - "hair", - "half", - "hall", - "hand", - "hang", - "harm", - "harp", - "hate", - "hawk", - "head", - "heat", - "heel", - "hell", - "helo", - "help", - "hemp", - "herb", - "hide", - "high", - "hill", - "hire", - "hive", - "hold", - "hole", - "home", - "hood", - "hoof", - "hook", - "hope", - "hops", - "horn", - "hose", - "host", - "hour", - "hunt", - "hurt", - "icon", - "idea", - "inch", - "iris", - "iron", - "item", - "jail", - "jeep", - "jeff", - "joey", - "join", - "joke", - "judo", - "jump", - "junk", - "jury", - "jute", - "kale", - "keep", - "kick", - "kill", - "kilt", - "kind", - "king", - "kiss", - "kite", - "knee", - "knot", - "lace", - "lack", - "lady", - "lake", - "lamb", - "lamp", - "land", - "lark", - "lava", - "lawn", - "lead", - "leaf", - "leek", - "lier", - "life", - "lift", - "lily", - "limo", - "line", - "link", - "lion", - "lisa", - "list", - "load", - "loaf", - "loan", - "lock", - "loft", - "long", - "look", - "loss", - "lout", - "love", - "luck", - "lung", - "lute", - "lynx", - "lyre", - "maid", - "mail", - "main", - "make", - "male", - "mall", - "manx", - "many", - "mare", - "mark", - "mask", - "mass", - "mate", - "math", - "meal", - "meat", - "meet", - "menu", - "mess", - "mice", - "midi", - "mile", - "milk", - "mime", - "mind", - "mine", - "mini", - "mint", - "miss", - "mist", - "moat", - "mode", - "mole", - "mood", - "moon", - "most", - "moth", - "move", - "mule", - "mutt", - "nail", - "name", - "neat", - "neck", - "need", - "neon", - "nest", - "news", - "node", - "nose", - "note", - "oboe", - "okra", - "open", - "oval", - "oven", - "oxen", - "pace", - "pack", - "page", - "pail", - "pain", - "pair", - "palm", - "pard", - "park", - "part", - "pass", - "past", - "path", - "peak", - "pear", - "peen", - "peer", - "pelt", - "perp", - "pest", - "pick", - "pier", - "pike", - "pile", - "pimp", - "pine", - "ping", - "pink", - "pint", - "pipe", - "piss", - "pith", - "plan", - "play", - "plot", - "plow", - "poem", - "poet", - "pole", - "polo", - "pond", - "pony", - "poof", - "pool", - "port", - "post", - "prow", - "pull", - "puma", - "pump", - "pupa", - "push", - "quit", - "race", - "rack", - "raft", - "rage", - "rail", - "rain", - "rake", - "rank", - "rate", - "read", - "rear", - "reef", - "rent", - "rest", - "rice", - "rich", - "ride", - "ring", - "rise", - "risk", - "road", - "robe", - "rock", - "role", - "roll", - "roof", - "room", - "root", - "rope", - "rose", - "ruin", - "rule", - "rush", - "ruth", - "sack", - "safe", - "sage", - "sail", - "sale", - "salt", - "sand", - "sari", - "sash", - "save", - "scow", - "seal", - "seat", - "seed", - "self", - "sell", - "shed", - "shin", - "ship", - "shoe", - "shop", - "shot", - "show", - "sick", - "side", - "sign", - "silk", - "sill", - "silo", - "sing", - "sink", - "site", - "size", - "skin", - "sled", - "slip", - "smog", - "snob", - "snow", - "soap", - "sock", - "soda", - "sofa", - "soft", - "soil", - "song", - "soot", - "sort", - "soup", - "spot", - "spur", - "stag", - "star", - "stay", - "stem", - "step", - "stew", - "stop", - "stud", - "suck", - "suit", - "swan", - "swim", - "tail", - "tale", - "talk", - "tank", - "tard", - "task", - "taxi", - "team", - "tear", - "teen", - "tell", - "temp", - "tent", - "term", - "test", - "text", - "thaw", - "tile", - "till", - "time", - "tire", - "toad", - "toga", - "togs", - "tone", - "tool", - "toot", - "tote", - "tour", - "town", - "tram", - "tray", - "tree", - "trim", - "trip", - "tuba", - "tube", - "tuna", - "tune", - "turn", - "tutu", - "twig", - "type", - "unit", - "user", - "vane", - "vase", - "vast", - "veal", - "veil", - "vein", - "vest", - "vibe", - "view", - "vise", - "wait", - "wake", - "walk", - "wall", - "wash", - "wasp", - "wave", - "wear", - "weed", - "week", - "well", - "west", - "whip", - "wife", - "will", - "wind", - "wine", - "wing", - "wire", - "wish", - "wolf", - "wood", - "wool", - "word", - "work", - "worm", - "wrap", - "wren", - "yard", - "yarn", - "yawl", - "year", - "yoga", - "yoke", - "yurt", - "zinc", - "zone"] \ No newline at end of file diff --git a/src/status/libstatus/browser.nim b/src/status/libstatus/browser.nim deleted file mode 100644 index 7255a229d6..0000000000 --- a/src/status/libstatus/browser.nim +++ /dev/null @@ -1,27 +0,0 @@ -import core, ../types/[bookmark], json, chronicles - -proc storeBookmark*(url: string, name: string): Bookmark = - let payload = %* [{"url": url, "name": name}] - result = Bookmark(name: name, url: url) - try: - let resp = callPrivateRPC("browsers_storeBookmark", payload).parseJson["result"] - result.imageUrl = resp["imageUrl"].getStr - except Exception as e: - error "Error updating bookmark", msg = e.msg - discard - -proc updateBookmark*(ogUrl: string, url: string, name: string) = - let payload = %* [ogUrl, {"url": url, "name": name}] - try: - discard callPrivateRPC("browsers_updateBookmark", payload) - except Exception as e: - error "Error updating bookmark", msg = e.msg - discard - -proc getBookmarks*(): string = - let payload = %* [] - result = callPrivateRPC("browsers_getBookmarks", payload) - -proc deleteBookmark*(url: string) = - let payload = %* [url] - discard callPrivateRPC("browsers_deleteBookmark", payload) diff --git a/src/status/libstatus/chat.nim b/src/status/libstatus/chat.nim deleted file mode 100644 index 94739b019c..0000000000 --- a/src/status/libstatus/chat.nim +++ /dev/null @@ -1,592 +0,0 @@ -import json, times, strutils, sequtils, chronicles, json_serialization, algorithm, strformat, sugar -import core, ../utils -import ../types/[chat, message, community, activity_center_notification, - status_update, rpc_response, setting, sticker] -import ./settings as status_settings - -proc buildFilter*(chat: Chat):JsonNode = - if chat.chatType == ChatType.PrivateGroupChat: - return newJNull() - result = %* { "ChatID": chat.id, "OneToOne": chat.chatType == ChatType.OneToOne } - -proc loadFilters*(filters: seq[JsonNode]): string = - result = callPrivateRPC("loadFilters".prefix, %* [filter(filters, proc(x:JsonNode):bool = x.kind != JNull)]) - -proc removeFilters*(chatId: string, filterId: string) = - discard callPrivateRPC("removeFilters".prefix, %* [ - [{ "ChatID": chatId, "FilterID": filterId }] - ]) - -proc saveChat*(chatId: string, chatType: ChatType, active: bool = true, color: string = "#000000", ensName: string = "", profile: string = "", joined: int64 = 0) = - # TODO: ideally status-go/stimbus should handle some of these fields instead of having the client - # send them: lastMessage, unviewedMEssagesCount, timestamp, lastClockValue, name? - discard callPrivateRPC("saveChat".prefix, %* [ - { - "lastClockValue": 0, # TODO: - "color": color, - "name": (if ensName != "": ensName else: chatId), - "lastMessage": nil, # TODO: - "active": active, - "profile": profile, - "id": chatId, - "unviewedMessagesCount": 0, # TODO: - "chatType": chatType.int, - "timestamp": 1588940692659, # TODO: - "joined": joined - } - ]) - -proc createPublicChat*(chatId: string):string = - callPrivateRPC("createPublicChat".prefix, %* [{"ID": chatId}]) - -proc createOneToOneChat*(chatId: string):string = - callPrivateRPC("createOneToOneChat".prefix, %* [{"ID": chatId}]) - -proc deactivateChat*(chat: Chat):string = - chat.isActive = false - callPrivateRPC("deactivateChat".prefix, %* [{ "ID": chat.id }]) - -proc createProfileChat*(pubKey: string):string = - callPrivateRPC("createProfileChat".prefix, %* [{ "ID": pubKey }]) - -proc sortChats(x, y: Chat): int = - var t1 = x.lastMessage.whisperTimestamp - var t2 = y.lastMessage.whisperTimestamp - - if t1 <= $x.joined: - t1 = $x.joined - if t2 <= $y.joined: - t2 = $y.joined - - if t1 > t2: 1 - elif t1 == t2: 0 - else: -1 - -proc loadChats*(): seq[Chat] = - result = @[] - let jsonResponse = parseJson($callPrivateRPC("chats".prefix)) - if jsonResponse["result"].kind != JNull: - for jsonChat in jsonResponse{"result"}: - let chat = jsonChat.toChat - if chat.isActive and chat.chatType != ChatType.Unknown: - result.add(chat) - result.sort(sortChats) - -proc parseActivityCenterNotifications*(rpcResult: JsonNode): (string, seq[ActivityCenterNotification]) = - var notifs: seq[ActivityCenterNotification] = @[] - var msg: Message - if rpcResult{"notifications"}.kind != JNull: - for jsonMsg in rpcResult["notifications"]: - notifs.add(jsonMsg.toActivityCenterNotification()) - return (rpcResult{"cursor"}.getStr, notifs) - -proc statusUpdates*(): seq[StatusUpdate] = - let rpcResult = callPrivateRPC("statusUpdates".prefix, %* []).parseJson()["result"] - if rpcResult != nil and rpcResult{"statusUpdates"} != nil and rpcResult["statusUpdates"].len != 0: - for jsonStatusUpdate in rpcResult["statusUpdates"]: - result.add(jsonStatusUpdate.toStatusUpdate) - -proc fetchChatMessages*(chatId: string, cursorVal: string, limit: int, success: var bool): string = - success = true - try: - result = callPrivateRPC("chatMessages".prefix, %* [chatId, cursorVal, limit]) - except RpcException as e: - success = false - result = e.msg - -proc editMessage*(messageId: string, msg: string): string = - callPrivateRPC("editMessage".prefix, %* [ - { - "id": messageId, - "text": msg - } - ]) - -proc deleteMessageAndSend*(messageId: string): string = - callPrivateRPC("deleteMessageAndSend".prefix, %* [messageId]) - -proc rpcReactions*(chatId: string, cursorVal: string, limit: int, success: var bool): string = - success = true - try: - result = callPrivateRPC("emojiReactionsByChatID".prefix, %* [chatId, cursorVal, limit]) - except RpcException as e: - success = false - result = e.msg - -proc addEmojiReaction*(chatId: string, messageId: string, emojiId: int): seq[Reaction] = - let rpcResult = parseJson(callPrivateRPC("sendEmojiReaction".prefix, %* [chatId, messageId, emojiId]))["result"] - - var reactions: seq[Reaction] = @[] - if rpcResult != nil and rpcResult["emojiReactions"] != nil and rpcResult["emojiReactions"].len != 0: - for jsonMsg in rpcResult["emojiReactions"]: - reactions.add(jsonMsg.toReaction) - - result = reactions - -proc removeEmojiReaction*(emojiReactionId: string): seq[Reaction] = - let rpcResult = parseJson(callPrivateRPC("sendEmojiReactionRetraction".prefix, %* [emojiReactionId]))["result"] - - var reactions: seq[Reaction] = @[] - if rpcResult != nil and rpcResult["emojiReactions"] != nil and rpcResult["emojiReactions"].len != 0: - for jsonMsg in rpcResult["emojiReactions"]: - reactions.add(jsonMsg.toReaction) - - result = reactions - -# TODO this probably belongs in another file -proc generateSymKeyFromPassword*(): string = - result = ($parseJson(callPrivateRPC("waku_generateSymKeyFromPassword", %* [ - # TODO unhardcode this for non-status mailservers - "status-offline-inbox" - ]))["result"]).strip(chars = {'"'}) - -proc sendChatMessage*(chatId: string, msg: string, replyTo: string, contentType: int, communityId: string = ""): string = - let preferredUsername = getSetting[string](Setting.PreferredUsername, "") - callPrivateRPC("sendChatMessage".prefix, %* [ - { - "chatId": chatId, - "text": msg, - "responseTo": replyTo, - "ensName": preferredUsername, - "sticker": nil, - "contentType": contentType, - "communityId": communityId - } - ]) - -proc sendImageMessage*(chatId: string, image: string): string = - let preferredUsername = getSetting[string](Setting.PreferredUsername, "") - callPrivateRPC("sendChatMessage".prefix, %* [ - { - "chatId": chatId, - "contentType": ContentType.Image.int, - "imagePath": image, - "ensName": preferredUsername, - "text": "Update to latest version to see a nice image here!" - } - ]) - -proc sendImageMessages*(chatId: string, images: var seq[string]): string = - let - preferredUsername = getSetting[string](Setting.PreferredUsername, "") - let imagesJson = %* images.map(image => %* - { - "chatId": chatId, - "contentType": ContentType.Image.int, - "imagePath": image, - "ensName": preferredUsername, - "text": "Update to latest version to see a nice image here!" - } - ) - callPrivateRPC("sendChatMessages".prefix, %* [imagesJson]) - -proc sendStickerMessage*(chatId: string, replyTo: string, sticker: Sticker): string = - let preferredUsername = getSetting[string](Setting.PreferredUsername, "") - callPrivateRPC("sendChatMessage".prefix, %* [ - { - "chatId": chatId, - "text": "Update to latest version to see a nice sticker here!", - "responseTo": replyTo, - "ensName": preferredUsername, - "sticker": { - "hash": sticker.hash, - "pack": sticker.packId - }, - "contentType": ContentType.Sticker.int - } - ]) - -proc markAllRead*(chatId: string): string = - callPrivateRPC("markAllRead".prefix, %* [chatId]) - -proc markMessagesSeen*(chatId: string, messageIds: seq[string]): string = - callPrivateRPC("markMessagesSeen".prefix, %* [chatId, messageIds]) - -proc confirmJoiningGroup*(chatId: string): string = - callPrivateRPC("confirmJoiningGroup".prefix, %* [chatId]) - -proc leaveGroupChat*(chatId: string): string = - callPrivateRPC("leaveGroupChat".prefix, %* [nil, chatId, true]) - -proc clearChatHistory*(chatId: string): string = - callPrivateRPC("deleteMessagesByChatID".prefix, %* [chatId]) - -proc deleteMessage*(messageId: string): string = - callPrivateRPC("deleteMessage".prefix, %* [messageId]) - -proc renameGroup*(chatId: string, newName: string): string = - callPrivateRPC("changeGroupChatName".prefix, %* [nil, chatId, newName]) - -proc createGroup*(groupName: string, pubKeys: seq[string]): string = - callPrivateRPC("createGroupChatWithMembers".prefix, %* [nil, groupName, pubKeys]) - -proc createGroupChatFromInvitation*(groupName: string, chatID: string, adminPK: string): string = - callPrivateRPC("createGroupChatFromInvitation".prefix, %* [groupName, chatID, adminPK]) - -proc addGroupMembers*(chatId: string, pubKeys: seq[string]): string = - callPrivateRPC("addMembersToGroupChat".prefix, %* [nil, chatId, pubKeys]) - -proc kickGroupMember*(chatId: string, pubKey: string): string = - callPrivateRPC("removeMemberFromGroupChat".prefix, %* [nil, chatId, pubKey]) - -proc makeAdmin*(chatId: string, pubKey: string): string = - callPrivateRPC("addAdminsToGroupChat".prefix, %* [nil, chatId, [pubKey]]) - -proc updateOutgoingMessageStatus*(messageId: string, status: string): string = - result = callPrivateRPC("updateMessageOutgoingStatus".prefix, %* [messageId, status]) - # TODO: handle errors - -proc reSendChatMessage*(messageId: string): string = - result = callPrivateRPC("reSendChatMessage".prefix, %*[messageId]) - -proc muteChat*(chatId: string): string = - result = callPrivateRPC("muteChat".prefix, %*[chatId]) - -proc unmuteChat*(chatId: string): string = - result = callPrivateRPC("unmuteChat".prefix, %*[chatId]) - -proc getLinkPreviewData*(link: string, success: var bool): JsonNode = - let - responseStr = callPrivateRPC("getLinkPreviewData".prefix, %*[link]) - response = Json.decode(responseStr, RpcResponseTyped[JsonNode], allowUnknownFields = false) - - if not response.error.isNil: - success = false - return %* { "error": fmt"""Error getting link preview data for '{link}': {response.error.message}""" } - - success = true - response.result - -proc getAllComunities*(): seq[Community] = - var communities: seq[Community] = @[] - let rpcResult = callPrivateRPC("communities".prefix).parseJSON() - if rpcResult{"result"}.kind != JNull: - for jsonCommunity in rpcResult["result"]: - var community = jsonCommunity.toCommunity() - - communities.add(community) - return communities - -proc getJoinedComunities*(): seq[Community] = - var communities: seq[Community] = @[] - let rpcResult = callPrivateRPC("joinedCommunities".prefix).parseJSON() - if rpcResult{"result"}.kind != JNull: - for jsonCommunity in rpcResult["result"]: - var community = jsonCommunity.toCommunity() - - communities.add(community) - return communities - -proc createCommunity*(name: string, description: string, access: int, ensOnly: bool, color: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int): Community = - let rpcResult = callPrivateRPC("createCommunity".prefix, %*[{ - # TODO this will need to be renamed membership (small m) - "Membership": access, - "name": name, - "description": description, - "ensOnly": ensOnly, - "color": color, - "image": imageUrl, - "imageAx": aX, - "imageAy": aY, - "imageBx": bX, - "imageBy": bY - }]).parseJSON() - - if rpcResult{"error"} != nil: - let error = Json.decode($rpcResult{"error"}, RpcError) - raise newException(RpcException, "Error creating community: " & error.message) - - if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull: - result = rpcResult["result"]["communities"][0].toCommunity() - -proc editCommunity*(communityId: string, name: string, description: string, access: int, ensOnly: bool, color: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int): Community = - let rpcResult = callPrivateRPC("editCommunity".prefix, %*[{ - # TODO this will need to be renamed membership (small m) - "CommunityID": communityId, - "Membership": access, - "name": name, - "description": description, - "ensOnly": ensOnly, - "color": color, - "image": imageUrl, - "imageAx": aX, - "imageAy": aY, - "imageBx": bX, - "imageBy": bY - }]).parseJSON() - - if rpcResult{"error"} != nil: - let error = Json.decode($rpcResult{"error"}, RpcError) - raise newException(RpcException, "Error editing community: " & error.message) - - if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull: - result = rpcResult["result"]["communities"][0].toCommunity() - -proc createCommunityChannel*(communityId: string, name: string, description: string): Chat = - let rpcResult = callPrivateRPC("createCommunityChat".prefix, %*[ - communityId, - { - "permissions": { - "access": 1 # TODO get this from user selected privacy setting - }, - "identity": { - "display_name": name, - "description": description#, - # "color": color#, - # TODO add images once it is supported by Status-Go - # "images": [ - # { - # "payload": image, - # # TODO get that from an enum - # "image_type": 1 # 1 is a raw payload - # } - # ] - } - }]).parseJSON() - - if rpcResult{"error"} != nil: - let error = Json.decode($rpcResult{"error"}, RpcError) - raise newException(RpcException, "Error creating community channel: " & error.message) - - if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull: - result = rpcResult["result"]["chats"][0].toChat() - -proc editCommunityChannel*(communityId: string, channelId: string, name: string, description: string, categoryId: string): Chat = - let rpcResult = callPrivateRPC("editCommunityChat".prefix, %*[ - communityId, - channelId.replace(communityId, ""), - { - "permissions": { - "access": 1 # TODO get this from user selected privacy setting - }, - "identity": { - "display_name": name, - "description": description#, - # "color": color#, - # TODO add images once it is supported by Status-Go - # "images": [ - # { - # "payload": image, - # # TODO get that from an enum - # "image_type": 1 # 1 is a raw payload - # } - # ] - }, - "category_id": categoryId - }]).parseJSON() - - if rpcResult{"error"} != nil: - let error = Json.decode($rpcResult{"error"}, RpcError) - raise newException(RpcException, "Error editing community channel: " & error.message) - - if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull: - result = rpcResult["result"]["chats"][0].toChat() - -proc deleteCommunityChat*(communityId: string, chatId: string) = - discard callPrivateRPC("deleteCommunityChat".prefix, %*[communityId, chatId]) - -proc createCommunityCategory*(communityId: string, name: string, channels: seq[string]): CommunityCategory = - let rpcResult = callPrivateRPC("createCommunityCategory".prefix, %*[ - { - "communityId": communityId, - "categoryName": name, - "chatIds": channels - }]).parseJSON() - - if rpcResult.contains("error"): - raise newException(StatusGoException, rpcResult["error"]["message"].getStr()) - else: - for k, v in rpcResult["result"]["communityChanges"].getElems()[0]["categoriesAdded"].pairs(): - result.id = v["category_id"].getStr() - result.name = v["name"].getStr() - result.position = v{"position"}.getInt() - - -proc editCommunityCategory*(communityId: string, categoryId: string, name: string, channels: seq[string]) = - let rpcResult = callPrivateRPC("editCommunityCategory".prefix, %*[ - { - "communityId": communityId, - "categoryId": categoryId, - "categoryName": name, - "chatIds": channels - }]).parseJSON() - if rpcResult.contains("error"): - raise newException(StatusGoException, rpcResult["error"]["message"].getStr()) - -proc reorderCommunityChat*(communityId: string, categoryId: string, chatId: string, position: int) = - let rpcResult = callPrivateRPC("reorderCommunityChat".prefix, %*[ - { - "communityId": communityId, - "categoryId": categoryId, - "chatId": chatId, - "position": position - }]).parseJSON() - if rpcResult.contains("error"): - raise newException(StatusGoException, rpcResult["error"]["message"].getStr()) - -proc reorderCommunityCategories*(communityId: string, categoryId: string, position: int) = - let rpcResult = callPrivateRPC("reorderCommunityCategories".prefix, %*[ - { - "communityId": communityId, - "categoryId": categoryId, - "position": position - }]).parseJSON() - if rpcResult.contains("error"): - raise newException(StatusGoException, rpcResult["error"]["message"].getStr()) - - -proc deleteCommunityCategory*(communityId: string, categoryId: string) = - let rpcResult = callPrivateRPC("deleteCommunityCategory".prefix, %*[ - { - "communityId": communityId, - "categoryId": categoryId - }]).parseJSON() - if rpcResult.contains("error"): - raise newException(StatusGoException, rpcResult["error"]["message"].getStr()) - -proc requestCommunityInfo*(communityId: string) = - discard callPrivateRPC("requestCommunityInfoFromMailserver".prefix, %*[communityId]) - -proc joinCommunity*(communityId: string) = - discard callPrivateRPC("joinCommunity".prefix, %*[communityId]) - -proc leaveCommunity*(communityId: string) = - discard callPrivateRPC("leaveCommunity".prefix, %*[communityId]) - -proc inviteUsersToCommunity*(communityId: string, pubKeys: seq[string]) = - discard callPrivateRPC("inviteUsersToCommunity".prefix, %*[{ - "communityId": communityId, - "users": pubKeys - }]) - -proc exportCommunity*(communityId: string):string = - result = callPrivateRPC("exportCommunity".prefix, %*[communityId]).parseJson()["result"].getStr - -proc importCommunity*(communityKey: string): string = - return callPrivateRPC("importCommunity".prefix, %*[communityKey]) - -proc removeUserFromCommunity*(communityId: string, pubKey: string) = - discard callPrivateRPC("removeUserFromCommunity".prefix, %*[communityId, pubKey]) - -proc requestToJoinCommunity*(communityId: string, ensName: string): seq[CommunityMembershipRequest] = - let rpcResult = callPrivateRPC("requestToJoinCommunity".prefix, %*[{ - "communityId": communityId, - "ensName": ensName - }]).parseJSON() - - var communityRequests: seq[CommunityMembershipRequest] = @[] - if rpcResult{"result"}{"requestsToJoinCommunity"} != nil and rpcResult{"result"}{"requestsToJoinCommunity"}.kind != JNull: - for jsonCommunityReqest in rpcResult["result"]["requestsToJoinCommunity"]: - communityRequests.add(jsonCommunityReqest.toCommunityMembershipRequest()) - - return communityRequests - -proc acceptRequestToJoinCommunity*(requestId: string) = - discard callPrivateRPC("acceptRequestToJoinCommunity".prefix, %*[{ - "id": requestId - }]) - -proc declineRequestToJoinCommunity*(requestId: string) = - discard callPrivateRPC("declineRequestToJoinCommunity".prefix, %*[{ - "id": requestId - }]) - -proc pendingRequestsToJoinForCommunity*(communityId: string): seq[CommunityMembershipRequest] = - let rpcResult = callPrivateRPC("pendingRequestsToJoinForCommunity".prefix, %*[communityId]).parseJSON() - - var communityRequests: seq[CommunityMembershipRequest] = @[] - - if rpcResult{"result"}.kind != JNull: - for jsonCommunityReqest in rpcResult["result"]: - communityRequests.add(jsonCommunityReqest.toCommunityMembershipRequest()) - - return communityRequests - -proc myPendingRequestsToJoin*(): seq[CommunityMembershipRequest] = - let rpcResult = callPrivateRPC("myPendingRequestsToJoin".prefix).parseJSON() - var communityRequests: seq[CommunityMembershipRequest] = @[] - - if rpcResult.hasKey("result") and rpcResult{"result"}.kind != JNull: - for jsonCommunityReqest in rpcResult["result"]: - communityRequests.add(jsonCommunityReqest.toCommunityMembershipRequest()) - - return communityRequests - -proc banUserFromCommunity*(pubKey: string, communityId: string): string = - return callPrivateRPC("banUserFromCommunity".prefix, %*[{ - "communityId": communityId, - "user": pubKey - }]) - -proc setCommunityMuted*(communityId: string, muted: bool) = - discard callPrivateRPC("setCommunityMuted".prefix, %*[communityId, muted]) - -proc rpcPinnedChatMessages*(chatId: string, cursorVal: string, limit: int, success: var bool): string = - success = true - try: - result = callPrivateRPC("chatPinnedMessages".prefix, %* [chatId, cursorVal, limit]) - except RpcException as e: - success = false - result = e.msg - -proc setPinMessage*(messageId: string, chatId: string, pinned: bool) = - discard callPrivateRPC("sendPinMessage".prefix, %*[{ - "message_id": messageId, - "pinned": pinned, - "chat_id": chatId - }]) - -proc rpcActivityCenterNotifications*(cursorVal: JsonNode, limit: int, success: var bool): string = - success = true - try: - result = callPrivateRPC("activityCenterNotifications".prefix, %* [cursorVal, limit]) - except RpcException as e: - success = false - result = e.msg - -proc activityCenterNotification*(cursor: string = ""): (string, seq[ActivityCenterNotification]) = - var cursorVal: JsonNode - - if cursor == "": - cursorVal = newJNull() - else: - cursorVal = newJString(cursor) - - var success: bool - let callResult = rpcActivityCenterNotifications(cursorVal, 20, success) - if success: - result = parseActivityCenterNotifications(callResult.parseJson()["result"]) - -proc markAllActivityCenterNotificationsRead*() = - discard callPrivateRPC("markAllActivityCenterNotificationsRead".prefix, %*[]) - -proc markActivityCenterNotificationsRead*(ids: seq[string]) = - discard callPrivateRPC("markActivityCenterNotificationsRead".prefix, %*[ids]) - -proc acceptActivityCenterNotifications*(ids: seq[string]): string = - result = callPrivateRPC("acceptActivityCenterNotifications".prefix, %*[ids]) - -proc dismissActivityCenterNotifications*(ids: seq[string]): string = - result = callPrivateRPC("dismissActivityCenterNotifications".prefix, %*[ids]) - -proc unreadActivityCenterNotificationsCount*(): int = - let rpcResult = callPrivateRPC("unreadActivityCenterNotificationsCount".prefix, %*[]).parseJson - - if rpcResult{"result"}.kind != JNull: - return rpcResult["result"].getInt - -proc asyncSearchMessages*(chatId: string, searchTerm: string, caseSensitive: bool, success: var bool): string = - success = true - try: - result = callPrivateRPC("allMessagesFromChatWhichMatchTerm".prefix, %* [chatId, searchTerm, caseSensitive]) - except RpcException as e: - success = false - result = e.msg - -proc asyncSearchMessages*(communityIds: seq[string], chatIds: seq[string], searchTerm: string, caseSensitive: bool, success: var bool): string = - success = true - try: - result = callPrivateRPC("allMessagesFromChatsAndCommunitiesWhichMatchTerm".prefix, %* [communityIds, chatIds, searchTerm, caseSensitive]) - except RpcException as e: - success = false - result = e.msg diff --git a/src/status/libstatus/chatCommands.nim b/src/status/libstatus/chatCommands.nim deleted file mode 100644 index 679bd14209..0000000000 --- a/src/status/libstatus/chatCommands.nim +++ /dev/null @@ -1,20 +0,0 @@ -import json, chronicles -import core, ../utils - -proc acceptRequestAddressForTransaction*(messageId: string, address: string): string = - result = callPrivateRPC("acceptRequestAddressForTransaction".prefix, %* [messageId, address]) - -proc declineRequestAddressForTransaction*(messageId: string): string = - result = callPrivateRPC("declineRequestAddressForTransaction".prefix, %* [messageId]) - -proc declineRequestTransaction*(messageId: string): string = - result = callPrivateRPC("declineRequestTransaction".prefix, %* [messageId]) - -proc requestAddressForTransaction*(chatId: string, fromAddress: string, amount: string, tokenAddress: string): string = - result = callPrivateRPC("requestAddressForTransaction".prefix, %* [chatId, fromAddress, amount, tokenAddress]) - -proc requestTransaction*(chatId: string, fromAddress: string, amount: string, tokenAddress: string): string = - result = callPrivateRPC("requestTransaction".prefix, %* [chatId, amount, tokenAddress, fromAddress]) - -proc acceptRequestTransaction*(transactionHash: string, messageId: string, signature: string): string = - result = callPrivateRPC("acceptRequestTransaction".prefix, %* [transactionHash, messageId, signature]) diff --git a/src/status/libstatus/coder.nim b/src/status/libstatus/coder.nim deleted file mode 100644 index c058ee0f7b..0000000000 --- a/src/status/libstatus/coder.nim +++ /dev/null @@ -1,77 +0,0 @@ -import macros -import web3/[encoding, ethtypes], stint - -type - GetPackData* = object - packId*: Stuint[256] - - PackData* = object - category*: DynamicBytes[32] # bytes4[] - owner*: Address # address - mintable*: bool # bool - timestamp*: Stuint[256] # uint256 - price*: Stuint[256] # uint256 - contentHash*: DynamicBytes[64] # bytes - - BuyToken* = object - packId*: Stuint[256] - address*: Address - price*: Stuint[256] - - Register* = object - label*: FixedBytes[32] - account*: Address - x*: FixedBytes[32] - y*: FixedBytes[32] - - SetPubkey* = object - label*: FixedBytes[32] - x*: FixedBytes[32] - y*: FixedBytes[32] - - ExpirationTime* = object - label*: FixedBytes[32] - - Release* = object - label*: FixedBytes[32] - - ApproveAndCall*[N: static[int]] = object - to*: Address - value*: Stuint[256] - data*: DynamicBytes[N] - - Transfer* = object - to*: Address - value*: Stuint[256] - - BalanceOf* = object - address*: Address - - TokenOfOwnerByIndex* = object - address*: Address - index*: Stuint[256] - - TokenPackId* = object - tokenId*: Stuint[256] - - TokenUri* = object - tokenId*: Stuint[256] - -# TODO: Figure out a way to parse a bool as a Bool instead of bool, as it is -# done in nim-web3 -func decode*(input: string, offset: int, to: var bool): int {.inline.} = - let val = input[offset..offset+63].parse(Int256) - to = val.truncate(int) == 1 - 64 - -# TODO: This is taken directly from nim-web3 in order to be able to decode -# booleans. I could not get the type Bool, as used in nim-web3, to be decoded -# properly, and instead resorted to a standard bool type. -func decodeHere*(input: string, offset: int, obj: var object): int = - var offset = offset - for field in fields(obj): - offset += decode(input, offset, field) - -func decodeContractResponse*[T](input: string): T = - result = T() - discard decodeHere(input.strip0xPrefix, 0, result) \ No newline at end of file diff --git a/src/status/libstatus/contacts.nim b/src/status/libstatus/contacts.nim deleted file mode 100644 index 4e54ab8d5e..0000000000 --- a/src/status/libstatus/contacts.nim +++ /dev/null @@ -1,45 +0,0 @@ -import json, strmisc, atomics -import core, ../utils - -var - contacts {.threadvar.}: JsonNode - contactsInited {.threadvar.}: bool - dirty: Atomic[bool] - -proc getContactByID*(id: string): string = - result = callPrivateRPC("getContactByID".prefix, %* [id]) - dirty.store(true) - -proc getContacts*(): JsonNode = - let cacheIsDirty = (not contactsInited) or dirty.load - if not cacheIsDirty: - result = contacts - else: - let payload = %* [] - let response = callPrivateRPC("contacts".prefix, payload).parseJson - if response["result"].kind == JNull: - result = %* [] - else: - result = response["result"] - dirty.store(false) - contacts = result - contactsInited = true - -proc saveContact*(id: string, ensVerified: bool, ensName: string, alias: string, identicon: string, thumbnail: string, systemTags: seq[string], localNickname: string): string = - let payload = %* [{ - "id": id, - "name": ensName, - "ensVerified": ensVerified, - "alias": alias, - "identicon": identicon, - "images": {"thumbnail": {"Payload": thumbnail.partition(",")[2]}}, - "systemTags": systemTags, - "localNickname": localNickname - }] - # TODO: StatusGoError handling - result = callPrivateRPC("saveContact".prefix, payload) - dirty.store(true) - -proc requestContactUpdate*(publicKey: string): string = - result = callPrivateRPC("sendContactUpdate".prefix, %* [publicKey, "", ""]) - dirty.store(true) diff --git a/src/status/libstatus/conversions.nim b/src/status/libstatus/conversions.nim deleted file mode 100644 index 5eee54698e..0000000000 --- a/src/status/libstatus/conversions.nim +++ /dev/null @@ -1,29 +0,0 @@ -import - json, options, strutils - -import - web3/[conversions, ethtypes], stint - -# 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] - -# TODO: update this in nim-web3 -proc `%`*(x: EthSend): JsonNode = - result = newJobject() - result["from"] = %x.source - 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.value.isSome: - result["value"] = %("0x" & x.value.unsafeGet.toHex) - result["data"] = %x.data - if x.nonce.isSome: - result["nonce"] = %x.nonce.unsafeGet \ No newline at end of file diff --git a/src/status/libstatus/core.nim b/src/status/libstatus/core.nim deleted file mode 100644 index b81717456d..0000000000 --- a/src/status/libstatus/core.nim +++ /dev/null @@ -1,59 +0,0 @@ -import json, nimcrypto, chronicles -import status_go, ../utils - -logScope: - topics = "rpc" - -proc callRPC*(inputJSON: string): string = - return $status_go.callRPC(inputJSON) - -proc callPrivateRPCRaw*(inputJSON: string): string = - return $status_go.callPrivateRPC(inputJSON) - -proc callPrivateRPC*(methodName: string, payload = %* []): string = - try: - let inputJSON = %* { - "jsonrpc": "2.0", - "method": methodName, - "params": %payload - } - debug "callPrivateRPC", rpc_method=methodName - let response = status_go.callPrivateRPC($inputJSON) - result = $response - if parseJSON(result).hasKey("error"): - writeStackTrace() - error "rpc response error", result, payload, methodName - except Exception as e: - error "error doing rpc request", methodName = methodName, exception=e.msg - -proc sendTransaction*(inputJSON: string, password: string): string = - var hashed_password = "0x" & $keccak_256.digest(password) - return $status_go.sendTransaction(inputJSON, hashed_password) - -proc startMessenger*() = - discard callPrivateRPC("startMessenger".prefix) - -proc addPeer*(peer: string) = - discard callPrivateRPC("admin_addPeer", %* [peer]) - -proc removePeer*(peer: string) = - discard callPrivateRPC("admin_removePeer", %* [peer]) - -proc markTrustedPeer*(peer: string) = - discard callPrivateRPC("markTrustedPeer".prefix(false), %* [peer]) - -proc getBlockByNumber*(blockNumber: string): string = - result = callPrivateRPC("eth_getBlockByNumber", %* [blockNumber, false]) - -proc getTransfersByAddress*(address: string, toBlock: string, limit: string, fetchMore: bool = false): string = - let toBlockParsed = if not fetchMore: newJNull() else: %toBlock - result = callPrivateRPC("wallet_getTransfersByAddress", %* [address, toBlockParsed, limit, fetchMore]) - -proc signMessage*(rpcParams: string): string = - return $status_go.signMessage(rpcParams) - -proc signTypedData*(data: string, address: string, password: string): string = - return $status_go.signTypedData(data, address, password) - -proc getBloomFilter*(): string = - return $callPrivateRPC("bloomFilter".prefix, %* []).parseJSON()["result"].getStr diff --git a/src/status/libstatus/edn_helpers.nim b/src/status/libstatus/edn_helpers.nim deleted file mode 100644 index f2873feeb2..0000000000 --- a/src/status/libstatus/edn_helpers.nim +++ /dev/null @@ -1,83 +0,0 @@ -import typetraits -import edn, chronicles -import ../types/[sticker] # FIXME: there should be no type deps - -# forward declaration: -proc parseNode[T](node: EdnNode, searchName: string): T -proc parseMap[T](map: HMap, searchName: string,): T - -proc getValueFromNode[T](node: EdnNode): T = - if node.kind == EdnSymbol: - when T is string: - result = node.symbol.name - elif node.kind == EdnKeyword: - when T is string: - result = node.keyword.name - elif node.kind == EdnString: - when T is string: - result = node.str - elif node.kind == EdnCharacter: - when T is string: - result = node.character - elif node.kind == EdnBool: - when T is bool: - result = node.boolVal - elif node.kind == EdnInt: - when T is int: - try: - result = cast[int](node.num) - except: - warn "Returned 0 value for node, when value should have been ", val = $node.num - result = 0 - else: - raise newException(ValueError, "couldn't get '" & T.type.name & "'value from node: " & repr(node)) - -proc parseVector[T: seq[Sticker]](node: EdnNode, searchName: string): seq[Sticker] = - # TODO: make this generic to accept any seq[T]. Issue is that instantiating result - # like `result = T()` is not allowed when T is `seq[Sticker]` - # because seq[Sticker] isn't an object, whereas it works when T is - # an object type (like Sticker). IOW, Sticker is an object type, but seq[Sticker] - # is not - result = newSeq[Sticker]() - - for i in 0.. 0: - for iChild in 0.. contract.name == name and contract.network == network) - result = if found.len > 0: found[0] else: nil - -proc getContract*(name: string): Contract = - let network = settings.getCurrentNetwork() - getContract(network, name) - -proc getErc20ContractBySymbol*(contracts: seq[Erc20Contract], symbol: string): Erc20Contract = - let found = contracts.filter(contract => contract.symbol.toLower == symbol.toLower) - result = if found.len > 0: found[0] else: nil - -proc getErc20ContractByAddress*(contracts: seq[Erc20Contract], address: Address): Erc20Contract = - let found = contracts.filter(contract => contract.address == address) - result = if found.len > 0: found[0] else: nil - -proc getErc20Contract*(symbol: string): Erc20Contract = - let network = settings.getCurrentNetwork() - result = allContracts().filter(contract => contract.network == network and contract of Erc20Contract).map(contract => Erc20Contract(contract)).getErc20ContractBySymbol(symbol) - -proc getErc20Contract*(address: Address): Erc20Contract = - let network = settings.getCurrentNetwork() - result = allContracts().filter(contract => contract.network == network and contract of Erc20Contract).map(contract => Erc20Contract(contract)).getErc20ContractByAddress(address) - -proc getErc20Contracts*(): seq[Erc20Contract] = - let network = settings.getCurrentNetwork() - result = allContracts().filter(contract => contract of Erc20Contract and contract.network == network).map(contract => Erc20Contract(contract)) - -proc getErc721Contract(network: Network, name: string): Erc721Contract = - let found = allContracts().filter(contract => contract of Erc721Contract and Erc721Contract(contract).name.toLower == name.toLower and contract.network == network) - result = if found.len > 0: Erc721Contract(found[0]) else: nil - -proc getErc721Contract*(name: string): Erc721Contract = - let network = settings.getCurrentNetwork() - getErc721Contract(network, name) - -proc getErc721Contracts*(): seq[Erc721Contract] = - let network = settings.getCurrentNetwork() - result = allContracts().filter(contract => contract of Erc721Contract and contract.network == network).map(contract => Erc721Contract(contract)) - -proc getSntContract*(): Erc20Contract = - if settings.getCurrentNetwork() == Network.Mainnet: - result = getErc20Contract("snt") - else: - result = getErc20Contract("stt") - if result == nil: - # TODO: xDai network does not have an SNT contract listed. We will need to handle - # having no SNT contract in other places in the code (ie anywhere that - # getSntContract() is called) - raise newException(ValueError, "A status contract could not be found for the current network") \ No newline at end of file diff --git a/src/status/libstatus/eth/eth.nim b/src/status/libstatus/eth/eth.nim deleted file mode 100644 index 23e442ce9e..0000000000 --- a/src/status/libstatus/eth/eth.nim +++ /dev/null @@ -1,23 +0,0 @@ -import - web3/ethtypes - -import - transactions, ../../types/[rpc_response] - -proc sendTransaction*(tx: var EthSend, password: string, success: var bool): string = - success = true - try: - let response = transactions.sendTransaction(tx, password) - result = response.result - except RpcException as e: - success = false - result = e.msg - -proc estimateGas*(tx: var EthSend, success: var bool): string = - success = true - try: - let response = transactions.estimateGas(tx) - result = response.result - except RpcException as e: - success = false - result = e.msg \ No newline at end of file diff --git a/src/status/libstatus/eth/methods.nim b/src/status/libstatus/eth/methods.nim deleted file mode 100644 index 85653f46a9..0000000000 --- a/src/status/libstatus/eth/methods.nim +++ /dev/null @@ -1,64 +0,0 @@ -import - strutils, options - -import - nimcrypto, web3/[encoding, ethtypes] - -import - ../../types/[rpc_response], ../coder, eth, transactions - -export sendTransaction - -type Method* = object - name*: string - signature*: string - -proc encodeMethod(self: Method): string = - ($nimcrypto.keccak256.digest(self.signature))[0..<8].toLower - -proc encodeAbi*(self: Method, obj: object = RootObj()): string = - result = "0x" & self.encodeMethod() - - # .fields is an iterator, and there's no way to get a count of an iterator - # in nim, so we have to loop and increment a counter - var fieldCount = 0 - for i in obj.fields: - fieldCount += 1 - var - offset = 32*fieldCount - data = "" - - for field in obj.fields: - let encoded = encode(field) - if encoded.dynamic: - result &= offset.toHex(64).toLower - data &= encoded.data - offset += encoded.data.len - else: - result &= encoded.data - result &= data - -proc estimateGas*(self: Method, tx: var EthSend, methodDescriptor: object, success: var bool): string = - success = true - tx.data = self.encodeAbi(methodDescriptor) - try: - let response = transactions.estimateGas(tx) - result = response.result # gas estimate in hex - except RpcException as e: - success = false - result = e.msg - -proc send*(self: Method, tx: var EthSend, methodDescriptor: object, password: string, success: var bool): string = - tx.data = self.encodeAbi(methodDescriptor) - result = eth.sendTransaction(tx, password, success) - -proc call*[T](self: Method, tx: var EthSend, methodDescriptor: object, success: var bool): T = - success = true - tx.data = self.encodeAbi(methodDescriptor) - let response: RpcResponse - try: - response = transactions.call(tx) - except RpcException as e: - success = false - result = e.msg - result = coder.decodeContractResponse[T](response.result) \ No newline at end of file diff --git a/src/status/libstatus/eth/transactions.nim b/src/status/libstatus/eth/transactions.nim deleted file mode 100644 index ee647ff66a..0000000000 --- a/src/status/libstatus/eth/transactions.nim +++ /dev/null @@ -1,30 +0,0 @@ -import - json - -import - json_serialization, chronicles, web3/ethtypes - -import - ../core, ../../types/[rpc_response], ../conversions - -proc estimateGas*(tx: EthSend): RpcResponse = - let response = core.callPrivateRPC("eth_estimateGas", %*[%tx]) - result = Json.decode(response, RpcResponse) - if not result.error.isNil: - raise newException(RpcException, "Error getting gas estimate: " & result.error.message) - - trace "Gas estimated succesfully", estimate=result.result - -proc sendTransaction*(tx: EthSend, password: string): RpcResponse = - let responseStr = core.sendTransaction($(%tx), password) - result = Json.decode(responseStr, RpcResponse) - if not result.error.isNil: - raise newException(RpcException, "Error sending transaction: " & result.error.message) - - trace "Transaction sent succesfully", hash=result.result - -proc call*(tx: EthSend): RpcResponse = - let responseStr = core.callPrivateRPC("eth_call", %*[%tx, "latest"]) - result = Json.decode(responseStr, RpcResponse) - if not result.error.isNil: - raise newException(RpcException, "Error calling method: " & result.error.message) \ No newline at end of file diff --git a/src/status/libstatus/gif.nim b/src/status/libstatus/gif.nim deleted file mode 100644 index a00afc68ad..0000000000 --- a/src/status/libstatus/gif.nim +++ /dev/null @@ -1,16 +0,0 @@ -import json - -import ./settings -import ../types/[setting] - -proc getRecentGifs*(): JsonNode = - return settings.getSetting[JsonNode](Setting.Gifs_Recent, %*{}) - -proc getFavoriteGifs*(): JsonNode = - return settings.getSetting[JsonNode](Setting.Gifs_Favorite, %*{}) - -proc setFavoriteGifs*(items: JsonNode) = - discard settings.saveSetting(Setting.Gifs_Favorite, items) - -proc setRecentGifs*(items: JsonNode) = - discard settings.saveSetting(Setting.Gifs_Recent, items) \ No newline at end of file diff --git a/src/status/libstatus/installations.nim b/src/status/libstatus/installations.nim deleted file mode 100644 index 5fdf2c9e1e..0000000000 --- a/src/status/libstatus/installations.nim +++ /dev/null @@ -1,29 +0,0 @@ -import json, core, ../utils, system - -var installations: JsonNode = %*{} -var dirty: bool = true - -proc setInstallationMetadata*(installationId: string, deviceName: string, deviceType: string): string = - result = callPrivateRPC("setInstallationMetadata".prefix, %* [installationId, {"name": deviceName, "deviceType": deviceType}]) - # TODO: handle errors - -proc getOurInstallations*(useCached: bool = true): JsonNode = - if useCached and not dirty: - return installations - installations = callPrivateRPC("getOurInstallations".prefix, %* []).parseJSON()["result"] - dirty = false - result = installations - -proc syncDevices*(preferredName: string): string = - # TODO change this to identicon when status-go is updated - let photoPath = "" - result = callPrivateRPC("syncDevices".prefix, %* [preferredName, photoPath]) - -proc sendPairInstallation*(): string = - result = callPrivateRPC("sendPairInstallation".prefix) - -proc enableInstallation*(installationId: string): string = - result = callPrivateRPC("enableInstallation".prefix, %* [installationId]) - -proc disableInstallation*(installationId: string): string = - result = callPrivateRPC("disableInstallation".prefix, %* [installationId]) diff --git a/src/status/libstatus/mailservers.nim b/src/status/libstatus/mailservers.nim deleted file mode 100644 index fab51cbb87..0000000000 --- a/src/status/libstatus/mailservers.nim +++ /dev/null @@ -1,49 +0,0 @@ -import json, times -import core, ../utils - -proc ping*(mailservers: seq[string], timeoutMs: int): string = - var addresses: seq[string] = @[] - for mailserver in mailservers: - addresses.add(mailserver) - result = callPrivateRPC("mailservers_ping", %* [ - { "addresses": addresses, "timeoutMs": timeoutMs } - ]) - -proc update*(peer: string) = - discard callPrivateRPC("updateMailservers".prefix, %* [[peer]]) - -proc setMailserver*(peer: string): string = - return callPrivateRPC("setMailserver".prefix, %* [peer]) - -proc delete*(peer: string) = - discard callPrivateRPC("mailservers_deleteMailserver", %* [peer]) - -proc requestAllHistoricMessages*(): string = - return callPrivateRPC("requestAllHistoricMessages".prefix, %*[]) - -proc requestStoreMessages*(topics: seq[string], symKeyID: string, peer: string, numberOfMessages: int, fromTimestamp: int64 = 0, toTimestamp: int64 = 0, force: bool = false) = - var toValue = times.toUnix(times.getTime()) - var fromValue = toValue - 86400 - if fromTimestamp != 0: - fromValue = fromTimestamp - if toTimestamp != 0: - toValue = toTimestamp - - echo callPrivateRPC("requestMessages".prefix, %* [ - { - "topics": topics, - "mailServerPeer": "16Uiu2HAmVVi6Q4j7MAKVibquW8aA27UNrA4Q8Wkz9EetGViu8ZF1", - "timeout": 30, - "limit": numberOfMessages, - "cursor": nil, - "from": fromValue, - "to": toValue, - "force": force - } - ]) - -proc syncChatFromSyncedFrom*(chatId: string): string = - return callPrivateRPC("syncChatFromSyncedFrom".prefix, %*[chatId]) - -proc fillGaps*(chatId: string, messageIds: seq[string]): string = - return callPrivateRPC("fillGaps".prefix, %*[chatId, messageIds]) diff --git a/src/status/libstatus/settings.nim b/src/status/libstatus/settings.nim deleted file mode 100644 index 274e4828a9..0000000000 --- a/src/status/libstatus/settings.nim +++ /dev/null @@ -1,215 +0,0 @@ -import - json, tables, sugar, sequtils, strutils, atomics, os - -import - json_serialization, chronicles, uuids - -import - ./core, ./accounts/constants, ../utils - -import ../types/[setting, network, fleet] -import ../../app_service/signals/[base] - -from status_go import nil - -var - settings {.threadvar.}: JsonNode - settingsInited {.threadvar.}: bool - dirty: Atomic[bool] - -dirty.store(true) -settings = %* {} - -proc saveSetting*(key: Setting, value: string | JsonNode | bool): StatusGoError = - try: - let response = callPrivateRPC("settings_saveSetting", %* [key, value]) - let responseResult = $(response.parseJSON(){"result"}) - if responseResult == "null": - result.error = "" - else: result = Json.decode(response, StatusGoError) - dirty.store(true) - except Exception as e: - error "Error saving setting", key=key, value=value, msg=e.msg - -proc getWeb3ClientVersion*(): string = - parseJson(callPrivateRPC("web3_clientVersion"))["result"].getStr - -proc getSettings*(useCached: bool = true, keepSensitiveData: bool = false): JsonNode = - let cacheIsDirty = (not settingsInited) or dirty.load - if useCached and (not cacheIsDirty) and (not keepSensitiveData): - result = settings - else: - var - allSettings = callPrivateRPC("settings_getSettings").parseJSON()["result"] - var - noSensitiveData = allSettings.deepCopy - noSensitiveData.delete("mnemonic") - if not keepSensitiveData: - result = noSensitiveData - else: - result = allSettings - dirty.store(false) - settings = noSensitiveData # never include sensitive data in cache - settingsInited = true - -proc getSetting*[T](name: Setting, defaultValue: T, useCached: bool = true): T = - let settings: JsonNode = getSettings(useCached, $name == "mnemonic") - if not settings.contains($name) or settings{$name}.isEmpty(): - return defaultValue - let value = $settings{$name} - try: - result = Json.decode(value, T) - except Exception as e: - error "Error decoding setting", name=name, value=value, msg=e.msg - return defaultValue - -proc getSetting*[T](name: Setting, useCached: bool = true): T = - result = getSetting(name, default(type(T)), useCached) - -proc getCurrentNetwork*(): Network = - case getSetting[string](Setting.Networks_CurrentNetwork, constants.DEFAULT_NETWORK_NAME): - of "mainnet_rpc": - result = Network.Mainnet - of "testnet_rpc": - result = Network.Testnet - of "rinkeby_rpc": - result = Network.Rinkeby - of "goerli_rpc": - result = Network.Goerli - of "xdai_rpc": - result = Network.XDai - of "poa_rpc": - result = Network.Poa - else: - result = Network.Other - -proc getCurrentNetworkDetails*(): NetworkDetails = - let currNetwork = getSetting[string](Setting.Networks_CurrentNetwork, constants.DEFAULT_NETWORK_NAME) - let networks = getSetting[seq[NetworkDetails]](Setting.Networks_Networks) - networks.find((network: NetworkDetails) => network.id == currNetwork) - -proc getLinkPreviewWhitelist*(): JsonNode = - result = callPrivateRPC("getLinkPreviewWhitelist".prefix, %* []).parseJSON()["result"] - -proc getFleet*(): Fleet = - let fleet = getSetting[string](Setting.Fleet, $Fleet.PROD) - result = parseEnum[Fleet](fleet) - -proc getPinnedMailserver*(): string = - let pinnedMailservers = getSetting[JsonNode](Setting.PinnedMailservers, %*{}) - let fleet = getSetting[string](Setting.Fleet, $Fleet.PROD) - return pinnedMailservers{fleet}.getStr() - -proc pinMailserver*(enode: string = "") = - let pinnedMailservers = getSetting[JsonNode](Setting.PinnedMailservers, %*{}) - let fleet = getSetting[string](Setting.Fleet, $Fleet.PROD) - - pinnedMailservers[fleet] = newJString(enode) - discard saveSetting(Setting.PinnedMailservers, pinnedMailservers) - -proc saveMailserver*(name, enode: string) = - let fleet = getSetting[string](Setting.Fleet, $Fleet.PROD) - let result = callPrivateRPC("mailservers_addMailserver", %* [ - %*{ - "id": $genUUID(), - "name": name, - "address": enode, - "fleet": $fleet - } - ]).parseJSON()["result"] - -proc getMailservers*():JsonNode = - let fleet = getSetting[string](Setting.Fleet, $Fleet.PROD) - result = callPrivateRPC("mailservers_getMailservers").parseJSON()["result"] - -proc getNodeConfig*():JsonNode = - result = status_go.getNodeConfig().parseJSON() - - # setting correct values in json - let currNetwork = getSetting[string](Setting.Networks_CurrentNetwork, constants.DEFAULT_NETWORK_NAME) - let networks = getSetting[JsonNode](Setting.Networks_Networks) - let networkConfig = networks.getElems().find((n:JsonNode) => n["id"].getStr() == currNetwork) - var newDataDir = networkConfig["config"]["DataDir"].getStr - newDataDir.removeSuffix("_rpc") - result["DataDir"] = newDataDir.newJString() - result["KeyStoreDir"] = newJString("./keystore") - result["LogFile"] = newJString("./geth.log") - result["ShhextConfig"]["BackupDisabledDataDir"] = newJString("./") - -proc getWakuVersion*():int = - let nodeConfig = getNodeConfig() - if nodeConfig["WakuConfig"]["Enabled"].getBool(): - return 1 - if nodeConfig["WakuV2Config"]["Enabled"].getBool(): - return 2 - return 0 - -proc setWakuVersion*(newVersion: int) = - let nodeConfig = getNodeConfig() - nodeConfig["RegisterTopics"] = %* @["whispermail"] - if newVersion == 1: - nodeConfig["WakuConfig"]["Enabled"] = newJBool(true) - nodeConfig["WakuV2Config"]["Enabled"] = newJBool(false) - nodeConfig["NoDiscovery"] = newJBool(false) - nodeConfig["Rendezvous"] = newJBool(true) - else: - nodeConfig["WakuConfig"]["Enabled"] = newJBool(false) - nodeConfig["WakuV2Config"]["Enabled"] = newJBool(true) - nodeConfig["NoDiscovery"] = newJBool(true) - nodeConfig["Rendezvous"] = newJBool(false) - discard saveSetting(Setting.NodeConfig, nodeConfig) - -proc setNetwork*(network: string): StatusGoError = - let statusGoResult = saveSetting(Setting.Networks_CurrentNetwork, network) - if statusGoResult.error != "": - return statusGoResult - - let networks = getSetting[JsonNode](Setting.Networks_Networks) - let networkConfig = networks.getElems().find((n:JsonNode) => n["id"].getStr() == network) - - var nodeConfig = getNodeConfig() - let upstreamUrl = networkConfig["config"]["UpstreamConfig"]["URL"] - var newDataDir = networkConfig["config"]["DataDir"].getStr - newDataDir.removeSuffix("_rpc") - - nodeConfig["NetworkId"] = networkConfig["config"]["NetworkId"] - nodeConfig["DataDir"] = newDataDir.newJString() - nodeConfig["UpstreamConfig"]["Enabled"] = networkConfig["config"]["UpstreamConfig"]["Enabled"] - nodeConfig["UpstreamConfig"]["URL"] = upstreamUrl - - return saveSetting(Setting.NodeConfig, nodeConfig) - -proc setBloomFilterMode*(bloomFilterMode: bool): StatusGoError = - let statusGoResult = saveSetting(Setting.WakuBloomFilterMode, bloomFilterMode) - if statusGoResult.error != "": - return statusGoResult - var nodeConfig = getNodeConfig() - nodeConfig["WakuConfig"]["BloomFilterMode"] = newJBool(bloomFilterMode) - return saveSetting(Setting.NodeConfig, nodeConfig) - -proc setBloomLevel*(bloomFilterMode: bool, fullNode: bool): StatusGoError = - let statusGoResult = saveSetting(Setting.WakuBloomFilterMode, bloomFilterMode) - if statusGoResult.error != "": - return statusGoResult - var nodeConfig = getNodeConfig() - nodeConfig["WakuConfig"]["BloomFilterMode"] = newJBool(bloomFilterMode) - nodeConfig["WakuConfig"]["FullNode"] = newJBool(fullNode) - nodeConfig["WakuConfig"]["LightClient"] = newJBool(not fullNode) - return saveSetting(Setting.NodeConfig, nodeConfig) - -proc setFleet*(fleetConfig: FleetConfig, fleet: Fleet): StatusGoError = - let statusGoResult = saveSetting(Setting.Fleet, $fleet) - if statusGoResult.error != "": - return statusGoResult - - var nodeConfig = getNodeConfig() - nodeConfig["ClusterConfig"]["Fleet"] = newJString($fleet) - nodeConfig["ClusterConfig"]["BootNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Bootnodes) - nodeConfig["ClusterConfig"]["TrustedMailServers"] = %* fleetConfig.getNodes(fleet, FleetNodes.Mailservers) - nodeConfig["ClusterConfig"]["StaticNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Whisper) - nodeConfig["ClusterConfig"]["RendezvousNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Rendezvous) - nodeConfig["ClusterConfig"]["WakuNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku) - nodeConfig["ClusterConfig"]["WakuStoreNodes"] = %* fleetConfig.getNodes(fleet, FleetNodes.Waku) - - return saveSetting(Setting.NodeConfig, nodeConfig) - diff --git a/src/status/libstatus/stickers.nim b/src/status/libstatus/stickers.nim deleted file mode 100644 index 71d22b1bd5..0000000000 --- a/src/status/libstatus/stickers.nim +++ /dev/null @@ -1,234 +0,0 @@ -import # std libs - atomics, json, tables, sequtils, httpclient, net -from strutils import parseHexInt, parseInt - -import # vendor libs - json_serialization, chronicles, libp2p/[multihash, multicodec, cid], stint, - web3/[ethtypes, conversions] -from nimcrypto import fromHex - -import # status-desktop libs - ./core as status, ../types/[sticker, setting, rpc_response], - ./eth/contracts, ./settings, ./edn_helpers - -proc decodeContentHash*(value: string): string = - if value == "": - return "" - - # eg encoded sticker multihash cid: - # e30101701220eab9a8ef4eac6c3e5836a3768d8e04935c10c67d9a700436a0e53199e9b64d29 - # e3017012205c531b83da9dd91529a4cf8ecd01cb62c399139e6f767e397d2f038b820c139f (testnet) - # e3011220c04c617170b1f5725070428c01280b4c19ae9083b7e6d71b7a0d2a1b5ae3ce30 (testnet) - # - # The first 4 bytes (in hex) represent: - # e3 = codec identifier "ipfs-ns" for content-hash - # 01 = unused - sometimes this is NOT included (ie ropsten) - # 01 = CID version (effectively unused, as we will decode with CIDv0 regardless) - # 70 = codec identifier "dag-pb" - - # ipfs-ns - if value[0..1] != "e3": - warn "Could not decode sticker. It may still be valid, but requires a different codec to be used", hash=value - return "" - - try: - # dag-pb - let defaultCodec = parseHexInt("70") #dag-pb - var codec = defaultCodec # no codec specified - var codecStartIdx = 2 # idx of where codec would start if it was specified - # handle the case when starts with 0xe30170 instead of 0xe3010170 - if value[2..5] == "0101": - codecStartIdx = 6 - codec = parseHexInt(value[6..7]) - elif value[2..3] == "01" and value[4..5] != "12": - codecStartIdx = 4 - codec = parseHexInt(value[4..5]) - - # strip the info we no longer need - var multiHashStr = value[codecStartIdx + 2.. -1: - visibleTokenList.del(symbolIdx) - else: - visibleTokenList.add symbol - visibleTokens[$currentNetwork] = newJArray() - visibleTokens[$currentNetwork] = %* visibleTokenList - let saved = saveSetting(Setting.VisibleTokens, $visibleTokens) - - convertStringSeqToERC20ContractSeq(visibleTokenList) - -proc hideAsset*(symbol: string) = - let currentNetwork = getCurrentNetwork() - let visibleTokens = visibleTokensSNTDefault() - var visibleTokenList = visibleTokens[$currentNetwork].to(seq[string]) - var symbolIdx = visibleTokenList.find(symbol) - if symbolIdx > -1: - visibleTokenList.del(symbolIdx) - visibleTokens[$currentNetwork] = newJArray() - visibleTokens[$currentNetwork] = %* visibleTokenList - discard saveSetting(Setting.VisibleTokens, $visibleTokens) - -proc getVisibleTokens*(): seq[Erc20Contract] = - let currentNetwork = getCurrentNetwork() - let visibleTokens = visibleTokensSNTDefault() - var visibleTokenList = visibleTokens[$currentNetwork].to(seq[string]) - let customTokens = getCustomTokens() - - result = convertStringSeqToERC20ContractSeq(visibleTokenList) - -proc addCustomToken*(address: string, name: string, symbol: string, decimals: int, color: string) = - let payload = %* [{"address": address, "name": name, "symbol": symbol, "decimals": decimals, "color": color}] - discard callPrivateRPC("wallet_addCustomToken", payload) - dirty.store(true) - -proc removeCustomToken*(address: string) = - let payload = %* [address] - echo callPrivateRPC("wallet_deleteCustomToken", payload) - dirty.store(true) - -proc getTokensBalances*(accounts: openArray[string], tokens: openArray[string]): JsonNode = - let payload = %* [accounts, tokens] - let response = callPrivateRPC("wallet_getTokensBalances", payload).parseJson - if response["result"].kind == JNull: - return %* {} - response["result"] - -proc getToken*(tokenAddress: string): Erc20Contract = - getErc20Contracts().concat(getCustomTokens()).getErc20ContractByAddress(tokenAddress.parseAddress) - -proc getTokenBalance*(tokenAddress: string, account: string): string = - var postfixedAccount: string = account - postfixedAccount.removePrefix("0x") - let payload = %* [{ - "to": tokenAddress, "from": account, "data": fmt"0x70a08231000000000000000000000000{postfixedAccount}" - }, "latest"] - let response = callPrivateRPC("eth_call", payload) - let balance = response.parseJson["result"].getStr - - var decimals = 18 - let address = parseAddress(tokenAddress) - let t = getErc20Contract(address) - let ct = getCustomTokens().getErc20ContractByAddress(address) - if t != nil: - decimals = t.decimals - elif ct != nil: - decimals = ct.decimals - - result = $hex2Token(balance, decimals) - -proc getSNTAddress*(): string = - let snt = contracts.getSntContract() - result = $snt.address - -proc getSNTBalance*(account: string): string = - let snt = contracts.getSntContract() - result = getTokenBalance($snt.address, account) - -proc getTokenString*(contract: Contract, methodName: string): string = - let payload = %* [{ - "to": $contract.address, - "data": contract.methods[methodName].encodeAbi() - }, "latest"] - - let responseStr = callPrivateRPC("eth_call", payload) - let response = Json.decode(responseStr, RpcResponse) - if not response.error.isNil: - raise newException(RpcException, "Error getting token string - " & methodName & ": " & response.error.message) - if response.result == "0x": - return "" - - let size = fromHex(Stuint[256], response.result[66..129]).truncate(int) - result = response.result[130..129+size*2].parseHexStr - -proc tokenName*(contract: Contract): string = getTokenString(contract, "name") - -proc tokenSymbol*(contract: Contract): string = getTokenString(contract, "symbol") - -proc tokenDecimals*(contract: Contract): int = - let payload = %* [{ - "to": $contract.address, - "data": contract.methods["decimals"].encodeAbi() - }, "latest"] - - let responseStr = callPrivateRPC("eth_call", payload) - let response = Json.decode(responseStr, RpcResponse) - if not response.error.isNil: - raise newException(RpcException, "Error getting token decimals: " & response.error.message) - if response.result == "0x": - return 0 - result = parseHexInt(response.result) diff --git a/src/status/libstatus/wallet.nim b/src/status/libstatus/wallet.nim deleted file mode 100644 index de5b37f79c..0000000000 --- a/src/status/libstatus/wallet.nim +++ /dev/null @@ -1,147 +0,0 @@ -import json, json, options, json_serialization, stint, chronicles -import core, conversions, ../types/[transaction, rpc_response], ../utils, strutils, strformat -from status_go import validateMnemonic#, startWallet -import ../wallet/account -import web3/ethtypes - -proc getWalletAccounts*(): seq[WalletAccount] = - try: - var response = callPrivateRPC("accounts_getAccounts") - let accounts = parseJson(response)["result"] - - var walletAccounts:seq[WalletAccount] = @[] - for account in accounts: - if (account["chat"].to(bool) == false): # Might need a better condition - walletAccounts.add(WalletAccount( - address: $account["address"].getStr, - path: $account["path"].getStr, - walletType: if (account.hasKey("type")): $account["type"].getStr else: "", - # Watch accoutns don't have a public key - publicKey: if (account.hasKey("public-key")): $account["public-key"].getStr else: "", - name: $account["name"].getStr, - iconColor: $account["color"].getStr, - wallet: account["wallet"].getBool, - chat: account["chat"].getBool, - )) - result = walletAccounts - except: - let msg = getCurrentExceptionMsg() - error "Failed getting wallet accounts", msg - -proc getTransactionReceipt*(transactionHash: string): string = - result = callPrivateRPC("eth_getTransactionReceipt", %* [transactionHash]) - -proc getTransfersByAddress*(address: string, toBlock: Uint256, limit: int, loadMore: bool = false): seq[Transaction] = - try: - let - toBlockParsed = "0x" & stint.toHex(toBlock) - limitParsed = "0x" & limit.toHex.stripLeadingZeros - transactionsResponse = getTransfersByAddress(address, toBlockParsed, limitParsed, loadMore) - transactions = parseJson(transactionsResponse)["result"] - var accountTransactions: seq[Transaction] = @[] - - for transaction in transactions: - accountTransactions.add(Transaction( - id: transaction["id"].getStr, - typeValue: transaction["type"].getStr, - address: transaction["address"].getStr, - contract: transaction["contract"].getStr, - blockNumber: transaction["blockNumber"].getStr, - blockHash: transaction["blockhash"].getStr, - timestamp: $hex2LocalDateTime(transaction["timestamp"].getStr()), - gasPrice: transaction["gasPrice"].getStr, - gasLimit: transaction["gasLimit"].getStr, - gasUsed: transaction["gasUsed"].getStr, - nonce: transaction["nonce"].getStr, - txStatus: transaction["txStatus"].getStr, - value: transaction["value"].getStr, - fromAddress: transaction["from"].getStr, - to: transaction["to"].getStr - )) - return accountTransactions - except: - let msg = getCurrentExceptionMsg() - error "Failed getting wallet account transactions", msg - -proc getBalance*(address: string): string = - let payload = %* [address, "latest"] - let response = parseJson(callPrivateRPC("eth_getBalance", payload)) - if response.hasKey("error"): - raise newException(RpcException, "Error getting balance: " & $response["error"]) - else: - result = response["result"].str - -proc hex2Eth*(input: string): string = - var value = fromHex(Stuint[256], input) - result = utils.wei2Eth(value) - -proc validateMnemonic*(mnemonic: string): string = - result = $status_go.validateMnemonic(mnemonic) - -proc startWallet*(watchNewBlocks: bool) = - # this will be fixed in a later PR - discard - -proc hex2Token*(input: string, decimals: int): string = - var value = fromHex(Stuint[256], input) - - if decimals == 0: - return fmt"{value}" - - var p = u256(10).pow(decimals) - var i = value.div(p) - var r = value.mod(p) - var leading_zeros = "0".repeat(decimals - ($r).len) - var d = fmt"{leading_zeros}{$r}" - result = $i - if(r > 0): result = fmt"{result}.{d}" - -proc trackPendingTransaction*(hash: string, fromAddress: string, toAddress: string, trxType: PendingTransactionType, data: string) = - let payload = %* [{"hash": hash, "from": fromAddress, "to": toAddress, "type": $trxType, "additionalData": data, "data": "", "value": 0, "timestamp": 0, "gasPrice": 0, "gasLimit": 0}] - discard callPrivateRPC("wallet_storePendingTransaction", payload) - -proc getPendingTransactions*(): string = - let payload = %* [] - try: - result = callPrivateRPC("wallet_getPendingTransactions", payload) - except Exception as e: - error "Error getting pending transactions (possible dev Infura key)", msg = e.msg - result = "" - - -proc getPendingOutboundTransactionsByAddress*(address: string): string = - let payload = %* [address] - result = callPrivateRPC("wallet_getPendingOutboundTransactionsByAddress", payload) - -proc deletePendingTransaction*(transactionHash: string) = - let payload = %* [transactionHash] - discard callPrivateRPC("wallet_deletePendingTransaction", payload) - -proc setInitialBlocksRange*(): string = - let payload = %* [] - result = callPrivateRPC("wallet_setInitialBlocksRange", payload) - -proc watchTransaction*(transactionHash: string): string = - let payload = %* [transactionHash] - result = callPrivateRPC("wallet_watchTransaction", payload) - -proc checkRecentHistory*(addresses: seq[string]): string = - let payload = %* [addresses] - result = callPrivateRPC("wallet_checkRecentHistory", payload) - -proc getOpenseaCollections*(address: string): string = - let payload = %* [address] - result = callPrivateRPC("wallet_getOpenseaCollectionsByOwner", payload) - -proc getOpenseaAssets*(address: string, collectionSlug: string, limit: int): string = - let payload = %* [address, collectionSlug, limit] - result = callPrivateRPC("wallet_getOpenseaAssetsByOwnerAndCollection", payload) - -proc fetchCryptoServices*(success: var bool): string = - success = true - try: - result = callPrivateRPC("wallet_getCryptoOnRamps") - except Exception as e: - success = false - error "Error getting crypto services: ", msg = e.msg - result = "" \ No newline at end of file diff --git a/src/status/mailservers.nim b/src/status/mailservers.nim deleted file mode 100644 index 42fbfb4d10..0000000000 --- a/src/status/mailservers.nim +++ /dev/null @@ -1,21 +0,0 @@ -import json - -import libstatus/mailservers as status_mailservers -import ../eventemitter - -type - MailserversModel* = ref object - events*: EventEmitter - -proc newMailserversModel*(events: EventEmitter): MailserversModel = - result = MailserversModel() - result.events = events - -proc fillGaps*(self: MailserversModel, chatId: string, messageIds: seq[string]): string = - result = status_mailservers.fillGaps(chatId, messageIds) - -proc setMailserver*(self: MailserversModel, peer: string): string = - result = status_mailservers.setMailserver(peer) - -proc requestAllHistoricMessages*(self: MailserversModel): string = - result = status_mailservers.requestAllHistoricMessages() \ No newline at end of file diff --git a/src/status/messages.nim b/src/status/messages.nim deleted file mode 100644 index 9c7c037fdc..0000000000 --- a/src/status/messages.nim +++ /dev/null @@ -1,51 +0,0 @@ -import tables, sets -import libstatus/chat -import ../eventemitter - -type - MessageDetails* = object - status*: string - chatId*: string - - MessagesModel* = ref object - events*: EventEmitter - messages*: Table[string, MessageDetails] - confirmations*: HashSet[string] - - MessageSentArgs* = ref object of Args - messageId*: string - chatId*: string - -proc newMessagesModel*(events: EventEmitter): MessagesModel = - result = MessagesModel() - result.events = events - result.messages = initTable[string, MessageDetails]() - result.confirmations = initHashSet[string]() - -proc delete*(self: MessagesModel) = - discard - -# For each message sent we call trackMessage to register the message id, -# and wait until an EnvelopeSent signals is emitted for that message. However -# due to communication being async, it's possible that the signal arrives -# first, hence why we check if there's a confirmation (an envelope.sent) -# inside trackMessage to emit the "messageSent" event - -proc trackMessage*(self: MessagesModel, messageId: string, chatId: string) = - if self.messages.hasKey(messageId): return - - self.messages[messageId] = MessageDetails(status: "sending", chatId: chatId) - if self.confirmations.contains(messageId): - self.confirmations.excl(messageId) - self.messages[messageId].status = "sent" - discard updateOutgoingMessageStatus(messageId, "sent") - self.events.emit("messageSent", MessageSentArgs(messageId: messageId, chatId: chatId)) - -proc updateStatus*(self: MessagesModel, messageIds: seq[string]) = - for messageId in messageIds: - if self.messages.hasKey(messageId): - self.messages[messageId].status = "sent" - discard updateOutgoingMessageStatus(messageId, "sent") - self.events.emit("messageSent", MessageSentArgs(messageId: messageId, chatId: self.messages[messageId].chatId)) - else: - self.confirmations.incl(messageId) diff --git a/src/status/network.nim b/src/status/network.nim deleted file mode 100644 index 95376a52b6..0000000000 --- a/src/status/network.nim +++ /dev/null @@ -1,54 +0,0 @@ -import chronicles -import ../eventemitter -import libstatus/settings -import json -import uuids -import json_serialization -import ./types/[setting] - -logScope: - topics = "network-model" - -type - NetworkModel* = ref object - peers*: seq[string] - events*: EventEmitter - connected*: bool - -proc newNetworkModel*(events: EventEmitter): NetworkModel = - result = NetworkModel() - result.events = events - result.peers = @[] - result.connected = false - -proc peerSummaryChange*(self: NetworkModel, peers: seq[string]) = - if peers.len == 0 and self.connected: - self.connected = false - self.events.emit("network:disconnected", Args()) - - if peers.len > 0 and not self.connected: - self.connected = true - self.events.emit("network:connected", Args()) - - self.peers = peers - -proc peerCount*(self: NetworkModel): int = self.peers.len - -proc isConnected*(self: NetworkModel): bool = self.connected - -proc addNetwork*(self: NetworkModel, name: string, endpoint: string, networkId: int, networkType: string) = - var networks = getSetting[JsonNode](Setting.Networks_Networks) - let id = genUUID() - networks.elems.add(%*{ - "id": $genUUID(), - "name": name, - "config": { - "NetworkId": networkId, - "DataDir": "/ethereum/" & networkType, - "UpstreamConfig": { - "Enabled": true, - "URL": endpoint - } - } - }) - discard saveSetting(Setting.Networks_Networks, networks) diff --git a/src/status/node.nim b/src/status/node.nim deleted file mode 100644 index 23c1b5c30f..0000000000 --- a/src/status/node.nim +++ /dev/null @@ -1,16 +0,0 @@ -import libstatus/core as status -import ../eventemitter - -type NodeModel* = ref object - events*: EventEmitter - -proc newNodeModel*(): NodeModel = - result = NodeModel() - result.events = createEventEmitter() - -proc delete*(self: NodeModel) = - discard - -proc sendRPCMessageRaw*(self: NodeModel, msg: string): string = - echo "sending RPC message" - status.callPrivateRPCRaw(msg) diff --git a/src/status/notifications/os_notifications.nim b/src/status/notifications/os_notifications.nim deleted file mode 100644 index a379134dc3..0000000000 --- a/src/status/notifications/os_notifications.nim +++ /dev/null @@ -1,20 +0,0 @@ -import json - -import ../types/[os_notification] -import ../../eventemitter - -type OsNotifications* = ref object - events: EventEmitter - -proc delete*(self: OsNotifications) = - discard - -proc newOsNotifications*(events: EventEmitter): OsNotifications = - result = OsNotifications() - result.events = events - -proc onNotificationClicked*(self: OsNotifications, identifier: string) = - ## This slot is called once user clicks a notificaiton bubble, "identifier" - ## contains data which uniquely define that notification. - let details = toOsNotificationDetails(parseJson(identifier)) - self.events.emit("osNotificationClicked", OsNotificationsArgs(details: details)) \ No newline at end of file diff --git a/src/status/permissions.nim b/src/status/permissions.nim deleted file mode 100644 index 3883ac7e7c..0000000000 --- a/src/status/permissions.nim +++ /dev/null @@ -1,105 +0,0 @@ -import json -import strutils -import sets -import libstatus/core -import chronicles -import ../eventemitter -import sequtils - -type - Permission* {.pure.} = enum - Web3 = "web3", - ContactCode = "contact-code" - Unknown = "unknown" - -logScope: - topics = "permissions-model" - -type - PermissionsModel* = ref object - events*: EventEmitter - -proc toPermission*(value: string): Permission = - result = Permission.Unknown - try: - result = parseEnum[Permission](value) - except: - warn "Unknown permission requested", value - -proc newPermissionsModel*(events: EventEmitter): PermissionsModel = - result = PermissionsModel() - result.events = events - -proc init*(self: PermissionsModel) = - discard - -type Dapp* = object - name*: string - permissions*: HashSet[Permission] - -proc getDapps*(self: PermissionsModel): seq[Dapp] = - let response = callPrivateRPC("permissions_getDappPermissions") - result = @[] - for dapps in response.parseJson["result"].getElems(): - var dapp = Dapp( - name: dapps["dapp"].getStr(), - permissions: initHashSet[Permission]() - ) - for permission in dapps["permissions"].getElems(): - dapp.permissions.incl(permission.getStr().toPermission()) - result.add(dapp) - -proc getPermissions*(self: PermissionsModel, dapp: string): HashSet[Permission] = - let response = callPrivateRPC("permissions_getDappPermissions") - result = initHashSet[Permission]() - for dappPermission in response.parseJson["result"].getElems(): - if dappPermission["dapp"].getStr() == dapp: - if not dappPermission.hasKey("permissions"): return - for permission in dappPermission["permissions"].getElems(): - result.incl(permission.getStr().toPermission()) - -proc revoke*(self: PermissionsModel, permission: Permission) = - let response = callPrivateRPC("permissions_getDappPermissions") - var permissions = initHashSet[Permission]() - - for dapps in response.parseJson["result"].getElems(): - for currPerm in dapps["permissions"].getElems(): - let p = currPerm.getStr().toPermission() - if p != permission: - permissions.incl(p) - - discard callPrivateRPC("permissions_addDappPermissions", %*[{ - "dapp": dapps["dapp"].getStr(), - "permissions": permissions.toSeq() - }]) - -proc hasPermission*(self: PermissionsModel, dapp: string, permission: Permission): bool = - result = self.getPermissions(dapp).contains(permission) - -proc addPermission*(self: PermissionsModel, dapp: string, permission: Permission) = - var permissions = self.getPermissions(dapp) - permissions.incl(permission) - discard callPrivateRPC("permissions_addDappPermissions", %*[{ - "dapp": dapp, - "permissions": permissions.toSeq() - }]) - -proc revokePermission*(self: PermissionsModel, dapp: string, permission: Permission) = - var permissions = self.getPermissions(dapp) - permissions.excl(permission) - - if permissions.len == 0: - discard callPrivateRPC("permissions_deleteDappPermissions", %*[dapp]) - else: - discard callPrivateRPC("permissions_addDappPermissions", %*[{ - "dapp": dapp, - "permissions": permissions.toSeq() - }]) - -proc clearPermissions*(self: PermissionsModel, dapp: string) = - discard callPrivateRPC("permissions_deleteDappPermissions", %*[dapp]) - -proc clearPermissions*(self: PermissionsModel) = - let response = callPrivateRPC("permissions_getDappPermissions") - for dapps in response.parseJson["result"].getElems(): - discard callPrivateRPC("permissions_deleteDappPermissions", %*[dapps["dapp"].getStr()]) diff --git a/src/status/profile.nim b/src/status/profile.nim deleted file mode 100644 index 5cb83b927d..0000000000 --- a/src/status/profile.nim +++ /dev/null @@ -1,28 +0,0 @@ -import json -import ./types/[identity_image] -import profile/profile -import libstatus/core as libstatus_core -import libstatus/accounts as status_accounts -import libstatus/settings as status_settings -import ../eventemitter - -type - ProfileModel* = ref object - -proc newProfileModel*(): ProfileModel = - result = ProfileModel() - -proc logout*(self: ProfileModel) = - discard status_accounts.logout() - -proc getLinkPreviewWhitelist*(self: ProfileModel): JsonNode = - result = status_settings.getLinkPreviewWhitelist() - -proc storeIdentityImage*(self: ProfileModel, keyUID: string, imagePath: string, aX, aY, bX, bY: int): IdentityImage = - result = status_accounts.storeIdentityImage(keyUID, imagePath, aX, aY, bX, bY) - -proc getIdentityImage*(self: ProfileModel, keyUID: string): IdentityImage = - result = status_accounts.getIdentityImage(keyUID) - -proc deleteIdentityImage*(self: ProfileModel, keyUID: string): string = - result = status_accounts.deleteIdentityImage(keyUID) diff --git a/src/status/profile/mailserver.nim b/src/status/profile/mailserver.nim deleted file mode 100644 index c2ec0742ae..0000000000 --- a/src/status/profile/mailserver.nim +++ /dev/null @@ -1,3 +0,0 @@ -type - MailServer* = ref object - name*, endpoint*: string diff --git a/src/status/profile/profile.nim b/src/status/profile/profile.nim deleted file mode 100644 index 213b467d89..0000000000 --- a/src/status/profile/profile.nim +++ /dev/null @@ -1,29 +0,0 @@ -import json -import ../types/[profile, account] - -export profile - -const contactAdded* = ":contact/added" -const contactBlocked* = ":contact/blocked" -const contactRequest* = ":contact/request-received" - -proc isContact*(self: Profile): bool = - result = self.systemTags.contains(contactAdded) - -proc isBlocked*(self: Profile): bool = - result = self.systemTags.contains(contactBlocked) - -proc requestReceived*(self: Profile): bool = - result = self.systemTags.contains(contactRequest) - -proc toProfileModel*(account: Account): Profile = - result = Profile( - id: "", - username: account.name, - identicon: account.identicon, - alias: account.name, - ensName: "", - ensVerified: false, - appearance: 0, - systemTags: @[] - ) diff --git a/src/status/provider.nim b/src/status/provider.nim deleted file mode 100644 index ae22604360..0000000000 --- a/src/status/provider.nim +++ /dev/null @@ -1,276 +0,0 @@ -import ens, wallet, permissions, utils -import ../eventemitter -import ./types/[setting] -import utils -import libstatus/accounts -import libstatus/core -import libstatus/settings as status_settings -import json, json_serialization, sets, strutils -import chronicles -import nbaser -import stew/byteutils -from base32 import nil - -const HTTPS_SCHEME* = "https" -const IPFS_GATEWAY* = ".infura.status.im" -const SWARM_GATEWAY* = "swarm-gateways.net" - -const base58* = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" - -logScope: - topics = "provider-model" - -type - RequestTypes {.pure.} = enum - Web3SendAsyncReadOnly = "web3-send-async-read-only", - HistoryStateChanged = "history-state-changed", - APIRequest = "api-request" - Unknown = "unknown" - - ResponseTypes {.pure.} = enum - Web3SendAsyncCallback = "web3-send-async-callback", - APIResponse = "api-response", - Web3ResponseError = "web3-response-error" - -type - Payload = ref object - id: JsonNode - rpcMethod: string - - Web3SendAsyncReadOnly = ref object - messageId: JsonNode - payload: Payload - request: string - hostname: string - - APIRequest = ref object - isAllowed: bool - messageId: JsonNode - permission: Permission - hostname: string - -const AUTH_METHODS = toHashSet(["eth_accounts", "eth_coinbase", "eth_sendTransaction", "eth_sign", "keycard_signTypedData", "eth_signTypedData", "eth_signTypedData_v3", "personal_sign", "personal_ecRecover"]) -const SIGN_METHODS = toHashSet(["eth_sign", "personal_sign", "eth_signTypedData", "eth_signTypedData_v3"]) -const ACC_METHODS = toHashSet(["eth_accounts", "eth_coinbase"]) - -type ProviderModel* = ref object - events*: EventEmitter - permissions*: PermissionsModel - -proc newProviderModel*(events: EventEmitter, permissions: PermissionsModel): ProviderModel = - result = ProviderModel() - result.events = events - result.permissions = permissions - -proc requestType(message: string): RequestTypes = - let data = message.parseJson - result = RequestTypes.Unknown - try: - result = parseEnum[RequestTypes](data["type"].getStr()) - except: - warn "Unknown request type received", value=data["permission"].getStr() - -proc toWeb3SendAsyncReadOnly(message: string): Web3SendAsyncReadOnly = - let data = message.parseJson - result = Web3SendAsyncReadOnly( - messageId: data["messageId"], - request: $data["payload"], - hostname: data{"hostname"}.getStr(), - payload: Payload( - id: data["payload"]{"id"}, - rpcMethod: data["payload"]["method"].getStr() - ) - ) - -proc toAPIRequest(message: string): APIRequest = - let data = message.parseJson - - result = APIRequest( - messageId: data["messageId"], - isAllowed: data{"isAllowed"}.getBool(), - permission: data["permission"].getStr().toPermission(), - hostname: data{"hostname"}.getStr() - ) - -proc process(self: ProviderModel, data: Web3SendAsyncReadOnly): string = - if AUTH_METHODS.contains(data.payload.rpcMethod) and not self.permissions.hasPermission(data.hostname, Permission.Web3): - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "error": { - "code": 4100 - } - } - - if data.payload.rpcMethod == "eth_sendTransaction": - try: - let request = data.request.parseJson - let fromAddress = request["params"][0]["from"].getStr() - let to = request["params"][0]{"to"}.getStr() - let value = if (request["params"][0]["value"] != nil): - request["params"][0]["value"].getStr() - else: - "0" - let password = request["password"].getStr() - let selectedGasLimit = request["selectedGasLimit"].getStr() - let selectedGasPrice = request["selectedGasPrice"].getStr() - let txData = if (request["params"][0].hasKey("data") and request["params"][0]["data"].kind != JNull): - request["params"][0]["data"].getStr() - else: - "" - - var success: bool - var errorMessage = "" - var response = "" - var validInput: bool = true - - try: - validateTransactionInput(fromAddress, to, "", value, selectedGasLimit, selectedGasPrice, txData, "dummy") - except Exception as e: - validInput = false - success = false - errorMessage = e.msg - - if validInput: - # TODO make this async - response = wallet.sendTransaction(fromAddress, to, value, selectedGasLimit, selectedGasPrice, password, success, txData) - errorMessage = if not success: - if response == "": - "web3-response-error" - else: - response - else: - "" - - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "error": errorMessage, - "result": { - "jsonrpc": "2.0", - "id": data.payload.id, - "result": if (success): response else: "" - } - } - except Exception as e: - error "Error sending the transaction", msg = e.msg - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "error": { - "code": 4100, - "message": e.msg - } - } - - if SIGN_METHODS.contains(data.payload.rpcMethod): - try: - let request = data.request.parseJson - var params = request["params"] - let password = hashPassword(request["password"].getStr()) - let dappAddress = status_settings.getSetting[string](Setting.DappsAddress) - var rpcResult = "{}" - - case data.payload.rpcMethod: - of "eth_signTypedData", "eth_signTypedData_v3": - rpcResult = signTypedData(params[1].getStr(), dappAddress, password) - else: - rpcResult = signMessage($ %* { - "data": params[0].getStr(), - "password": password, - "account": dappAddress - }) - - let jsonRpcResult = rpcResult.parseJson - let success: bool = not jsonRpcResult.hasKey("error") - let errorMessage = if success: "" else: jsonRpcResult["error"]{"message"}.getStr() - let response = if success: jsonRpcResult["result"].getStr() else: "" - - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "error": errorMessage, - "result": { - "jsonrpc": "2.0", - "id": if data.payload.id == nil: newJNull() else: data.payload.id, - "result": if (success): response else: "" - } - } - - except Exception as e: - error "Error signing message", msg = e.msg - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "error": { - "code": 4100, - "message": e.msg - } - } - - - - if ACC_METHODS.contains(data.payload.rpcMethod): - let dappAddress = status_settings.getSetting[string](Setting.DappsAddress) - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "result": { - "jsonrpc": "2.0", - "id": data.payload.id, - "result": if data.payload.rpcMethod == "eth_coinbase": newJString(dappAddress) else: %*[dappAddress] - } - } - - let rpcResult = callRPC(data.request) - - return $ %* { - "type": ResponseTypes.Web3SendAsyncCallback, - "messageId": data.messageId, - "error": (if rpcResult == "": newJString("web3-response-error") else: newJNull()), - "result": rpcResult.parseJson - } - -proc process*(self: ProviderModel, data: APIRequest): string = - var value:JsonNode = case data.permission - of Permission.Web3: %* [status_settings.getSetting[string](Setting.DappsAddress, "0x0000000000000000000000000000000000000000")] - of Permission.ContactCode: %* status_settings.getSetting[string](Setting.PublicKey, "0x0") - of Permission.Unknown: newJNull() - - let isAllowed = data.isAllowed and data.permission != Permission.Unknown - - info "API request received", host=data.hostname, value=data.permission, isAllowed - - if isAllowed: self.permissions.addPermission(data.hostname, data.permission) - - return $ %* { - "type": ResponseTypes.APIResponse, - "isAllowed": isAllowed, - "permission": data.permission, - "messageId": data.messageId, - "data": value - } - -proc postMessage*(self: ProviderModel, message: string): string = - case message.requestType(): - of RequestTypes.Web3SendAsyncReadOnly: self.process(message.toWeb3SendAsyncReadOnly()) - of RequestTypes.HistoryStateChanged: """{"type":"TODO-IMPLEMENT-THIS"}""" ############# TODO: - of RequestTypes.APIRequest: self.process(message.toAPIRequest()) - else: """{"type":"TODO-IMPLEMENT-THIS"}""" ##################### TODO: - -proc ensResourceURL*(self: ProviderModel, ens: string, url: string): (string, string, string, string, bool) = - let contentHash = contenthash(ens) - if contentHash == "": # ENS does not have a content hash - return (url, url, HTTPS_SCHEME, "", false) - - let decodedHash = contentHash.decodeENSContentHash() - case decodedHash[0]: - of ENSType.IPFS: - let base32Hash = base32.encode(string.fromBytes(base58.decode(decodedHash[1]))).toLowerAscii().replace("=", "") - result = (url, base32Hash & IPFS_GATEWAY, HTTPS_SCHEME, "", true) - of ENSType.SWARM: - result = (url, SWARM_GATEWAY, HTTPS_SCHEME, "/bzz:/" & decodedHash[1] & "/", true) - of ENSType.IPNS: - result = (url, decodedHash[1], HTTPS_SCHEME, "", true) - else: - warn "Unknown content for", ens, contentHash diff --git a/src/status/settings.nim b/src/status/settings.nim deleted file mode 100644 index 8f30ac26f5..0000000000 --- a/src/status/settings.nim +++ /dev/null @@ -1,72 +0,0 @@ -import json, json_serialization - -import - sugar, sequtils, strutils, atomics - -import libstatus/settings as libstatus_settings -import ../eventemitter -import ./types/[fleet, network, setting] -import ../app_service/signals/[base] - -type - SettingsModel* = ref object - events*: EventEmitter - -proc newSettingsModel*(events: EventEmitter): SettingsModel = - result = SettingsModel() - result.events = events - -proc saveSetting*(self: SettingsModel, key: Setting, value: string | JsonNode | bool): StatusGoError = - result = libstatus_settings.saveSetting(key, value) - -proc getSetting*[T](self: SettingsModel, name: Setting, defaultValue: T, useCached: bool = true): T = - result = libstatus_settings.getSetting(name, defaultValue, useCached) - -proc getSetting*[T](self: SettingsModel, name: Setting, useCached: bool = true): T = - result = libstatus_settings.getSetting[T](name, useCached) - -# TODO: name with a 2 due to namespace conflicts that need to be addressed in subsquent PRs -proc getSetting2*[T](name: Setting, defaultValue: T, useCached: bool = true): T = - result = libstatus_settings.getSetting(name, defaultValue, useCached) - -proc getSetting2*[T](name: Setting, useCached: bool = true): T = - result = libstatus_settings.getSetting[T](name, useCached) - -proc getCurrentNetworkDetails*(self: SettingsModel): NetworkDetails = - result = libstatus_settings.getCurrentNetworkDetails() - -proc getMailservers*(self: SettingsModel):JsonNode = - result = libstatus_settings.getMailservers() - -proc getPinnedMailserver*(self: SettingsModel): string = - result = libstatus_settings.getPinnedMailserver() - -proc pinMailserver*(self: SettingsModel, enode: string = "") = - libstatus_settings.pinMailserver(enode) - -proc saveMailserver*(self: SettingsModel, name, enode: string) = - libstatus_settings.saveMailserver(name, enode) - -proc getFleet*(self: SettingsModel): Fleet = - result = libstatus_settings.getFleet() - -proc getCurrentNetwork*(): Network = - result = libstatus_settings.getCurrentNetwork() - -proc getCurrentNetwork*(self: SettingsModel): Network = - result = getCurrentNetwork() - -proc setWakuVersion*(self: SettingsModel, newVersion: int) = - libstatus_settings.setWakuVersion(newVersion) - -proc setBloomFilterMode*(self: SettingsModel, bloomFilterMode: bool): StatusGoError = - libstatus_settings.setBloomFilterMode(bloomFilterMode) - -proc setFleet*(self: SettingsModel, fleetConfig: FleetConfig, fleet: Fleet): StatusGoError = - libstatus_settings.setFleet(fleetConfig, fleet) - -proc getNodeConfig*(self: SettingsModel): JsonNode = - libstatus_settings.getNodeConfig() - -proc setBloomLevel*(self: SettingsModel, bloomFilterMode: bool, fullNode: bool): StatusGoError = - libstatus_settings.setBloomLevel(bloomFilterMode, fullNode) \ No newline at end of file diff --git a/src/status/status.nim b/src/status/status.nim deleted file mode 100644 index cef1dd326d..0000000000 --- a/src/status/status.nim +++ /dev/null @@ -1,89 +0,0 @@ -import libstatus/accounts as libstatus_accounts -import libstatus/core as libstatus_core -import libstatus/settings as libstatus_settings -import chat, accounts, wallet, wallet2, node, network, messages, contacts, profile, stickers, permissions, fleet, settings, mailservers, browser, tokens, provider -import notifications/os_notifications -import ../eventemitter -import bitops, stew/byteutils, chronicles -import ./types/[setting] - -export chat, accounts, node, messages, contacts, profile, network, permissions, fleet, eventemitter - -type Status* = ref object - events*: EventEmitter - fleet*: FleetModel - chat*: ChatModel - messages*: MessagesModel - accounts*: AccountModel - wallet*: WalletModel - wallet2*: StatusWalletController - node*: NodeModel - profile*: ProfileModel - contacts*: ContactModel - network*: NetworkModel - stickers*: StickersModel - permissions*: PermissionsModel - settings*: SettingsModel - mailservers*: MailserversModel - browser*: BrowserModel - tokens*: TokensModel - provider*: ProviderModel - osnotifications*: OsNotifications - -proc newStatusInstance*(fleetConfig: string): Status = - result = Status() - result.events = createEventEmitter() - result.fleet = fleet.newFleetModel(fleetConfig) - result.chat = chat.newChatModel(result.events) - result.accounts = accounts.newAccountModel(result.events) - result.wallet = wallet.newWalletModel(result.events) - result.wallet.initEvents() - result.wallet2 = wallet2.newStatusWalletController(result.events) - result.node = node.newNodeModel() - result.messages = messages.newMessagesModel(result.events) - result.profile = profile.newProfileModel() - result.contacts = contacts.newContactModel(result.events) - result.network = network.newNetworkModel(result.events) - result.stickers = stickers.newStickersModel(result.events) - result.permissions = permissions.newPermissionsModel(result.events) - result.settings = settings.newSettingsModel(result.events) - result.mailservers = mailservers.newMailserversModel(result.events) - result.browser = browser.newBrowserModel(result.events) - result.tokens = tokens.newTokensModel(result.events) - result.provider = provider.newProviderModel(result.events, result.permissions) - result.osnotifications = newOsNotifications(result.events) - -proc initNode*(self: Status) = - libstatus_accounts.initNode() - -proc startMessenger*(self: Status) = - libstatus_core.startMessenger() - -proc reset*(self: Status) = - # TODO: remove this once accounts are not tracked in the AccountsModel - self.accounts.reset() - - # NOT NEEDED self.chat.reset() - # NOT NEEDED self.wallet.reset() - # NOT NEEDED self.node.reset() - # NOT NEEDED self.mailservers.reset() - # NOT NEEDED self.profile.reset() - - # TODO: add all resets here - -proc getNodeVersion*(self: Status): string = - libstatus_settings.getWeb3ClientVersion() - -# TODO: duplicated?? -proc saveSetting*(self: Status, setting: Setting, value: string | bool) = - discard libstatus_settings.saveSetting(setting, value) - -proc getBloomFilter*(self: Status): string = - result = libstatus_core.getBloomFilter() - -proc getBloomFilterBitsSet*(self: Status): int = - let bloomFilter = libstatus_core.getBloomFilter() - var bitCount = 0; - for b in hexToSeqByte(bloomFilter): - bitCount += countSetBits(b) - return bitCount \ No newline at end of file diff --git a/src/status/stickers.nim b/src/status/stickers.nim deleted file mode 100644 index fae2d6d2ab..0000000000 --- a/src/status/stickers.nim +++ /dev/null @@ -1,146 +0,0 @@ -import # global deps - atomics, sequtils, strutils, tables - -import # project deps - chronicles, web3/[ethtypes, conversions], stint - -import # local deps - libstatus/eth/contracts as status_contracts, - libstatus/stickers as status_stickers, transactions, - libstatus/wallet, ../eventemitter -import ./types/[sticker, transaction, rpc_response] -from utils as libstatus_utils import eth2Wei, gwei2Wei, toUInt64, parseAddress - - -logScope: - topics = "stickers-model" - -type - StickersModel* = ref object - events*: EventEmitter - recentStickers*: seq[Sticker] - availableStickerPacks*: Table[int, StickerPack] - installedStickerPacks*: Table[int, StickerPack] - purchasedStickerPacks*: seq[int] - - StickerArgs* = ref object of Args - sticker*: Sticker - save*: bool - -# forward declaration -proc addStickerToRecent*(self: StickersModel, sticker: Sticker, save: bool = false) - -proc newStickersModel*(events: EventEmitter): StickersModel = - result = StickersModel() - result.events = events - result.recentStickers = @[] - result.availableStickerPacks = initTable[int, StickerPack]() - result.installedStickerPacks = initTable[int, StickerPack]() - result.purchasedStickerPacks = @[] - -proc init*(self: StickersModel) = - self.events.on("stickerSent") do(e: Args): - var evArgs = StickerArgs(e) - self.addStickerToRecent(evArgs.sticker, evArgs.save) - -proc buildTransaction(packId: Uint256, address: Address, price: Uint256, approveAndCall: var ApproveAndCall[100], sntContract: var Erc20Contract, gas = "", gasPrice = ""): EthSend = - sntContract = status_contracts.getSntContract() - let - stickerMktContract = status_contracts.getContract("sticker-market") - buyToken = BuyToken(packId: packId, address: address, price: price) - buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(buyToken) - approveAndCall = ApproveAndCall[100](to: stickerMktContract.address, value: price, data: DynamicBytes[100].fromHex(buyTxAbiEncoded)) - transactions.buildTokenTransaction(address, sntContract.address, gas, gasPrice) - -proc estimateGas*(packId: int, address: string, price: string, success: var bool): int = - var - approveAndCall: ApproveAndCall[100] - sntContract = status_contracts.getSntContract() - tx = buildTransaction( - packId.u256, - parseAddress(address), - eth2Wei(parseFloat(price), sntContract.decimals), - approveAndCall, - sntContract - ) - - let response = sntContract.methods["approveAndCall"].estimateGas(tx, approveAndCall, success) - if success: - result = fromHex[int](response) - -proc buyPack*(self: StickersModel, packId: int, address, price, gas, gasPrice, password: string, success: var bool): string = - var - sntContract: Erc20Contract - approveAndCall: ApproveAndCall[100] - tx = buildTransaction( - packId.u256, - parseAddress(address), - eth2Wei(parseFloat(price), 18), # SNT - approveAndCall, - sntContract, - gas, - gasPrice - ) - - result = sntContract.methods["approveAndCall"].send(tx, approveAndCall, password, success) - if success: - trackPendingTransaction(result, address, $sntContract.address, PendingTransactionType.BuyStickerPack, $packId) - -proc getStickerMarketAddress*(self: StickersModel): Address = - result = status_contracts.getContract("sticker-market").address - -proc getPurchasedStickerPacks*(self: StickersModel, address: Address): seq[int] = - try: - let - balance = status_stickers.getBalance(address) - tokenIds = toSeq[0.. 24: - self.recentStickers = self.recentStickers[0..23] # take top 24 most recent - if save: - status_stickers.saveRecentStickers(self.recentStickers) - -proc decodeContentHash*(value: string): string = - result = status_stickers.decodeContentHash(value) - -proc getPackIdFromTokenId*(tokenId: Stuint[256]): int = - result = status_stickers.getPackIdFromTokenId(tokenId) diff --git a/src/status/tokens.nim b/src/status/tokens.nim deleted file mode 100644 index 21c5fb1188..0000000000 --- a/src/status/tokens.nim +++ /dev/null @@ -1,43 +0,0 @@ -import libstatus/tokens as status_tokens -import libstatus/eth/contracts -import ../eventemitter - -type - TokensModel* = ref object - events*: EventEmitter - -proc newTokensModel*(events: EventEmitter): TokensModel = - result = TokensModel() - result.events = events - -proc getSNTAddress*(): string = - result = status_tokens.getSNTAddress() - -proc getCustomTokens*(self: TokensModel, useCached: bool = true): seq[Erc20Contract] = - result = status_tokens.getCustomTokens(useCached) - -proc removeCustomToken*(self: TokensModel, address: string) = - status_tokens.removeCustomToken(address) - -proc getSNTBalance*(account: string): string = - result = status_tokens.getSNTBalance(account) - -proc tokenDecimals*(contract: Contract): int = - result = status_tokens.tokenDecimals(contract) - -proc tokenName*(contract: Contract): string = - result = status_tokens.tokenName(contract) - -proc tokensymbol*(contract: Contract): string = - result = status_tokens.tokensymbol(contract) - -proc getTokenBalance*(tokenAddress: string, account: string): string = - result = status_tokens.getTokenBalance(tokenAddress, account) - -proc getToken*(self: TokensModel, tokenAddress: string): Erc20Contract = - result = status_tokens.getToken(tokenAddress) - -export newErc20Contract -export getErc20Contracts -export Erc20Contract -export getErc20ContractByAddress diff --git a/src/status/transactions.nim b/src/status/transactions.nim deleted file mode 100644 index c41801009e..0000000000 --- a/src/status/transactions.nim +++ /dev/null @@ -1,20 +0,0 @@ -import - options, strutils - -import - stint, web3/ethtypes - -from utils as status_utils import toUInt64, gwei2Wei, parseAddress - -proc buildTransaction*(source: Address, value: Uint256, gas = "", gasPrice = "", data = ""): EthSend = - result = EthSend( - source: source, - value: value.some, - gas: (if gas.isEmptyOrWhitespace: Quantity.none else: Quantity(cast[uint64](parseFloat(gas).toUInt64)).some), - gasPrice: (if gasPrice.isEmptyOrWhitespace: int.none else: gwei2Wei(parseFloat(gasPrice)).truncate(int).some), - data: data - ) - -proc buildTokenTransaction*(source, contractAddress: Address, gas = "", gasPrice = ""): EthSend = - result = buildTransaction(source, 0.u256, gas, gasPrice) - result.to = contractAddress.some \ No newline at end of file diff --git a/src/status/types/account.nim b/src/status/types/account.nim deleted file mode 100644 index de1eaac65a..0000000000 --- a/src/status/types/account.nim +++ /dev/null @@ -1,46 +0,0 @@ -{.used.} - -import json_serialization - -import ../../eventemitter -import identity_image - -include multi_accounts - -export identity_image - -type - Account* = ref object of RootObj - name*: string - keyUid* {.serializedFieldName("key-uid").}: string - identityImage*: IdentityImage - identicon*: string - -type - NodeAccount* = ref object of Account - timestamp*: int - keycardPairing* {.serializedFieldName("keycard-pairing").}: string - -type - GeneratedAccount* = ref object - publicKey*: string - address*: string - id*: string - mnemonic*: string - derived*: MultiAccounts - # FIXME: should inherit from Account but multiAccountGenerateAndDeriveAddresses - # response has a camel-cased properties like "publicKey" and "keyUid", so the - # serializedFieldName pragma would need to be different - name*: string - keyUid*: string - identicon*: string - identityImage*: IdentityImage - -proc toAccount*(account: GeneratedAccount): Account = - result = Account(name: account.name, identityImage: account.identityImage, identicon: account.identicon, keyUid: account.keyUid) - -proc toAccount*(account: NodeAccount): Account = - result = Account(name: account.name, identityImage: account.identityImage, identicon: account.identicon, keyUid: account.keyUid) - -type AccountArgs* = ref object of Args - account*: Account \ No newline at end of file diff --git a/src/status/types/activity_center_notification.nim b/src/status/types/activity_center_notification.nim deleted file mode 100644 index 5a988edbda..0000000000 --- a/src/status/types/activity_center_notification.nim +++ /dev/null @@ -1,49 +0,0 @@ -{.used.} - -import json, chronicles -import message - -export message - -type ActivityCenterNotificationType* {.pure.}= enum - Unknown = 0, - NewOneToOne = 1, - NewPrivateGroupChat = 2, - Mention = 3 - Reply = 4 - -type ActivityCenterNotification* = ref object of RootObj - id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat - chatId*: string - name*: string - author*: string - notificationType*: ActivityCenterNotificationType - message*: Message - timestamp*: int64 - read*: bool - dismissed*: bool - accepted*: bool - -proc toActivityCenterNotification*(jsonNotification: JsonNode): ActivityCenterNotification = - var activityCenterNotificationType: ActivityCenterNotificationType - try: - activityCenterNotificationType = ActivityCenterNotificationType(jsonNotification{"type"}.getInt) - except: - warn "Unknown notification type received", type = jsonNotification{"type"}.getInt - activityCenterNotificationType = ActivityCenterNotificationType.Unknown - result = ActivityCenterNotification( - id: jsonNotification{"id"}.getStr, - chatId: jsonNotification{"chatId"}.getStr, - name: jsonNotification{"name"}.getStr, - author: jsonNotification{"author"}.getStr, - notificationType: activityCenterNotificationType, - timestamp: jsonNotification{"timestamp"}.getInt, - read: jsonNotification{"read"}.getBool, - dismissed: jsonNotification{"dismissed"}.getBool, - accepted: jsonNotification{"accepted"}.getBool - ) - - if jsonNotification.contains("message") and jsonNotification{"message"}.kind != JNull: - result.message = jsonNotification{"message"}.toMessage() - elif activityCenterNotificationType == ActivityCenterNotificationType.NewOneToOne and jsonNotification.contains("lastMessage") and jsonNotification{"lastMessage"}.kind != JNull: - result.message = jsonNotification{"lastMessage"}.toMessage() \ No newline at end of file diff --git a/src/status/types/bookmark.nim b/src/status/types/bookmark.nim deleted file mode 100644 index 4da7bf9f93..0000000000 --- a/src/status/types/bookmark.nim +++ /dev/null @@ -1,7 +0,0 @@ -{.used.} - -type Bookmark* = ref object - name*: string - url*: string - imageUrl*: string - diff --git a/src/status/types/chat.nim b/src/status/types/chat.nim deleted file mode 100644 index b310654934..0000000000 --- a/src/status/types/chat.nim +++ /dev/null @@ -1,170 +0,0 @@ -{.used.} - -import strutils, random, strformat, json - -import ../libstatus/accounts as status_accounts -import message - -include chat_member -include chat_membership_event - -type ChatType* {.pure.}= enum - Unknown = 0, - OneToOne = 1, - Public = 2, - PrivateGroupChat = 3, - Profile = 4, - Timeline = 5 - CommunityChat = 6 - -proc isOneToOne*(self: ChatType): bool = self == ChatType.OneToOne -proc isTimeline*(self: ChatType): bool = self == ChatType.Timeline - -type Chat* = ref object - id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat - communityId*: string - private*: bool - categoryId*: string - name*: string - description*: string - color*: string - identicon*: string - isActive*: bool # indicates whether the chat has been soft deleted - chatType*: ChatType - timestamp*: int64 # indicates the last time this chat has received/sent a message - joined*: int64 # indicates when the user joined the chat last time - lastClockValue*: int64 # indicates the last clock value to be used when sending messages - deletedAtClockValue*: int64 # indicates the clock value at time of deletion, messages with lower clock value of this should be discarded - unviewedMessagesCount*: int - unviewedMentionsCount*: int - lastMessage*: Message - members*: seq[ChatMember] - membershipUpdateEvents*: seq[ChatMembershipEvent] - mentionsCount*: int # Using this is not a good approach, we should instead use unviewedMentionsCount and refer to it always. - muted*: bool - canPost*: bool - ensName*: string - position*: int - -proc `$`*(self: Chat): string = - result = fmt"Chat(id:{self.id}, name:{self.name}, active:{self.isActive}, type:{self.chatType})" - -proc toJsonNode*(self: Chat): JsonNode = - result = %* { - "active": self.isActive, - "chatType": self.chatType.int, - "color": self.color, - "deletedAtClockValue": self.deletedAtClockValue, - "id": self.id, - "lastClockValue": self.lastClockValue, - "lastMessage": nil, - "members": self.members.toJsonNode, - "membershipUpdateEvents": self.membershipUpdateEvents.toJsonNode, - "name": (if self.ensName != "": self.ensName else: self.name), - "timestamp": self.timestamp, - "unviewedMessagesCount": self.unviewedMessagesCount, - "joined": self.joined, - "position": self.position - } - -proc toChatMember*(jsonMember: JsonNode): ChatMember = - let pubkey = jsonMember["id"].getStr - - result = ChatMember( - admin: jsonMember["admin"].getBool, - id: pubkey, - joined: jsonMember["joined"].getBool, - identicon: generateIdenticon(pubkey), - userName: generateAlias(pubkey) - ) - -proc toChatMembershipEvent*(jsonMembership: JsonNode): ChatMembershipEvent = - result = ChatMembershipEvent( - chatId: jsonMembership["chatId"].getStr, - clockValue: jsonMembership["clockValue"].getBiggestInt, - fromKey: jsonMembership["from"].getStr, - rawPayload: jsonMembership["rawPayload"].getStr, - signature: jsonMembership["signature"].getStr, - eventType: jsonMembership["type"].getInt, - name: jsonMembership{"name"}.getStr, - members: @[] - ) - if jsonMembership{"members"} != nil: - for member in jsonMembership["members"]: - result.members.add(member.getStr) - -proc toChat*(jsonChat: JsonNode): Chat = - - let chatTypeInt = jsonChat{"chatType"}.getInt - let chatType: ChatType = if chatTypeInt >= ord(low(ChatType)) or chatTypeInt <= ord(high(ChatType)): ChatType(chatTypeInt) else: ChatType.Unknown - - result = Chat( - id: jsonChat{"id"}.getStr, - communityId: jsonChat{"communityId"}.getStr, - name: jsonChat{"name"}.getStr, - description: jsonChat{"description"}.getStr, - identicon: "", - color: jsonChat{"color"}.getStr, - isActive: jsonChat{"active"}.getBool, - chatType: chatType, - timestamp: jsonChat{"timestamp"}.getBiggestInt, - lastClockValue: jsonChat{"lastClockValue"}.getBiggestInt, - deletedAtClockValue: jsonChat{"deletedAtClockValue"}.getBiggestInt, - unviewedMessagesCount: jsonChat{"unviewedMessagesCount"}.getInt, - unviewedMentionsCount: jsonChat{"unviewedMentionsCount"}.getInt, - mentionsCount: 0, - muted: false, - ensName: "", - joined: 0, - private: jsonChat{"private"}.getBool - ) - - if jsonChat.hasKey("muted") and jsonChat["muted"].kind != JNull: - result.muted = jsonChat["muted"].getBool - - if jsonChat["lastMessage"].kind != JNull: - result.lastMessage = jsonChat{"lastMessage"}.toMessage() - - if jsonChat.hasKey("joined") and jsonChat["joined"].kind != JNull: - result.joined = jsonChat{"joined"}.getInt - - if result.chatType == ChatType.OneToOne: - result.identicon = generateIdenticon(result.id) - if result.name.endsWith(".eth"): - result.ensName = result.name - if result.name == "": - result.name = generateAlias(result.id) - - if jsonChat["members"].kind != JNull: - result.members = @[] - for jsonMember in jsonChat["members"]: - result.members.add(jsonMember.toChatMember) - - if jsonChat["membershipUpdateEvents"].kind != JNull: - result.membershipUpdateEvents = @[] - for jsonMember in jsonChat["membershipUpdateEvents"]: - result.membershipUpdateEvents.add(jsonMember.toChatMembershipEvent) - -const channelColors* = ["#fa6565", "#7cda00", "#887af9", "#51d0f0", "#FE8F59", "#d37ef4"] - -proc newChat*(id: string, chatType: ChatType): Chat = - randomize() - - result = Chat( - id: id, - color: channelColors[rand(channelColors.len - 1)], - isActive: true, - chatType: chatType, - timestamp: 0, - lastClockValue: 0, - deletedAtClockValue: 0, - unviewedMessagesCount: 0, - mentionsCount: 0, - members: @[] - ) - - if chatType == ChatType.OneToOne: - result.identicon = generateIdenticon(id) - result.name = generateAlias(id) - else: - result.name = id \ No newline at end of file diff --git a/src/status/types/chat_member.nim b/src/status/types/chat_member.nim deleted file mode 100644 index 718cb659ce..0000000000 --- a/src/status/types/chat_member.nim +++ /dev/null @@ -1,21 +0,0 @@ -{.used.} - -import strformat, json, sequtils - -type ChatMember* = object - admin*: bool - id*: string - joined*: bool - identicon*: string - userName*: string - localNickname*: string - -proc toJsonNode*(self: ChatMember): JsonNode = - result = %* { - "id": self.id, - "admin": self.admin, - "joined": self.joined - } - -proc toJsonNode*(self: seq[ChatMember]): seq[JsonNode] = - result = map(self, proc(x: ChatMember): JsonNode = x.toJsonNode) \ No newline at end of file diff --git a/src/status/types/chat_membership_event.nim b/src/status/types/chat_membership_event.nim deleted file mode 100644 index d0b048c069..0000000000 --- a/src/status/types/chat_membership_event.nim +++ /dev/null @@ -1,28 +0,0 @@ -{.used.} - -import strformat, json, sequtils - -type ChatMembershipEvent* = object - chatId*: string - clockValue*: int64 - fromKey*: string - name*: string - members*: seq[string] - rawPayload*: string - signature*: string - eventType*: int - -proc toJsonNode*(self: ChatMembershipEvent): JsonNode = - result = %* { - "chatId": self.chatId, - "name": self.name, - "clockValue": self.clockValue, - "from": self.fromKey, - "members": self.members, - "rawPayload": self.rawPayload, - "signature": self.signature, - "type": self.eventType - } - -proc toJsonNode*(self: seq[ChatMembershipEvent]): seq[JsonNode] = - result = map(self, proc(x: ChatMembershipEvent): JsonNode = x.toJsonNode) \ No newline at end of file diff --git a/src/status/types/community.nim b/src/status/types/community.nim deleted file mode 100644 index dbec307493..0000000000 --- a/src/status/types/community.nim +++ /dev/null @@ -1,91 +0,0 @@ -{.used.} - -import json, strformat, tables -import chat, status_update, identity_image - -include community_category -include community_membership_request - -type Community* = object - id*: string - name*: string - lastChannelSeen*: string - description*: string - chats*: seq[Chat] - categories*: seq[CommunityCategory] - members*: seq[string] - access*: int - unviewedMessagesCount*: int - unviewedMentionsCount*: int - admin*: bool - joined*: bool - verified*: bool - ensOnly*: bool - canRequestAccess*: bool - canManageUsers*: bool - canJoin*: bool - isMember*: bool - muted*: bool - communityImage*: IdentityImage - membershipRequests*: seq[CommunityMembershipRequest] - communityColor*: string - memberStatus*: OrderedTable[string, StatusUpdate] - -proc `$`*(self: Community): string = - result = fmt"Community(id:{self.id}, name:{self.name}, description:{self.description}" - -proc toCommunity*(jsonCommunity: JsonNode): Community = - result = Community( - id: jsonCommunity{"id"}.getStr, - name: jsonCommunity{"name"}.getStr, - description: jsonCommunity{"description"}.getStr, - access: jsonCommunity{"permissions"}{"access"}.getInt, - admin: jsonCommunity{"admin"}.getBool, - joined: jsonCommunity{"joined"}.getBool, - verified: jsonCommunity{"verified"}.getBool, - ensOnly: jsonCommunity{"permissions"}{"ens_only"}.getBool, - canRequestAccess: jsonCommunity{"canRequestAccess"}.getBool, - canManageUsers: jsonCommunity{"canManageUsers"}.getBool, - canJoin: jsonCommunity{"canJoin"}.getBool, - isMember: jsonCommunity{"isMember"}.getBool, - muted: jsonCommunity{"muted"}.getBool, - chats: newSeq[Chat](), - members: newSeq[string](), - communityColor: jsonCommunity{"color"}.getStr, - communityImage: IdentityImage() - ) - - result.memberStatus = initOrderedTable[string, StatusUpdate]() - - if jsonCommunity.hasKey("images") and jsonCommunity["images"].kind != JNull: - if jsonCommunity["images"].hasKey("thumbnail"): - result.communityImage.thumbnail = jsonCommunity["images"]["thumbnail"]["uri"].str - if jsonCommunity["images"].hasKey("large"): - result.communityImage.large = jsonCommunity["images"]["large"]["uri"].str - - if jsonCommunity.hasKey("chats") and jsonCommunity["chats"].kind != JNull: - for chatId, chat in jsonCommunity{"chats"}: - result.chats.add(Chat( - id: result.id & chatId, - categoryId: chat{"categoryID"}.getStr(), - communityId: result.id, - name: chat{"name"}.getStr, - description: chat{"description"}.getStr, - canPost: chat{"canPost"}.getBool, - chatType: ChatType.CommunityChat, - private: chat{"permissions"}{"private"}.getBool, - position: chat{"position"}.getInt - )) - - if jsonCommunity.hasKey("categories") and jsonCommunity["categories"].kind != JNull: - for catId, cat in jsonCommunity{"categories"}: - result.categories.add(CommunityCategory( - id: catId, - name: cat{"name"}.getStr, - position: cat{"position"}.getInt - )) - - if jsonCommunity.hasKey("members") and jsonCommunity["members"].kind != JNull: - # memberInfo is empty for now - for memberPubKey, memeberInfo in jsonCommunity{"members"}: - result.members.add(memberPubKey) \ No newline at end of file diff --git a/src/status/types/community_category.nim b/src/status/types/community_category.nim deleted file mode 100644 index 49cab308cb..0000000000 --- a/src/status/types/community_category.nim +++ /dev/null @@ -1,6 +0,0 @@ -{.used.} - -type CommunityCategory* = object - id*: string - name*: string - position*: int \ No newline at end of file diff --git a/src/status/types/community_membership_request.nim b/src/status/types/community_membership_request.nim deleted file mode 100644 index 7add50c156..0000000000 --- a/src/status/types/community_membership_request.nim +++ /dev/null @@ -1,21 +0,0 @@ -{.used.} - -import json - -type CommunityMembershipRequest* = object - id*: string - publicKey*: string - chatId*: string - communityId*: string - state*: int - our*: string - -proc toCommunityMembershipRequest*(jsonCommunityMembershipRequest: JsonNode): CommunityMembershipRequest = - result = CommunityMembershipRequest( - id: jsonCommunityMembershipRequest{"id"}.getStr, - publicKey: jsonCommunityMembershipRequest{"publicKey"}.getStr, - chatId: jsonCommunityMembershipRequest{"chatId"}.getStr, - state: jsonCommunityMembershipRequest{"state"}.getInt, - communityId: jsonCommunityMembershipRequest{"communityId"}.getStr, - our: jsonCommunityMembershipRequest{"our"}.getStr, - ) \ No newline at end of file diff --git a/src/status/types/derived_account.nim b/src/status/types/derived_account.nim deleted file mode 100644 index fd47d198e4..0000000000 --- a/src/status/types/derived_account.nim +++ /dev/null @@ -1,6 +0,0 @@ -{.used.} - -type DerivedAccount* = object - publicKey*: string - address*: string - derivationPath*: string \ No newline at end of file diff --git a/src/status/types/fleet.nim b/src/status/types/fleet.nim deleted file mode 100644 index bd5374b67a..0000000000 --- a/src/status/types/fleet.nim +++ /dev/null @@ -1,52 +0,0 @@ -{.used.} - -import json, typetraits, tables, sequtils - -type - Fleet* {.pure.} = enum - Prod = "eth.prod", - Staging = "eth.staging", - Test = "eth.test", - WakuV2Prod = "wakuv2.prod" - WakuV2Test = "wakuv2.test" - - FleetNodes* {.pure.} = enum - Bootnodes = "boot", - Mailservers = "mail", - Rendezvous = "rendezvous", - Whisper = "whisper", - Waku = "waku" - - FleetMeta* = object - hostname*: string - timestamp*: uint64 - - FleetConfig* = object - fleet*: Table[string, Table[string, Table[string, string]]] - meta*: FleetMeta - - -proc toFleetConfig*(jsonString: string): FleetConfig = - let fleetJson = jsonString.parseJSON - result.meta.hostname = fleetJson["meta"]["hostname"].getStr - result.meta.timestamp = fleetJson["meta"]["timestamp"].getBiggestInt.uint64 - result.fleet = initTable[string, Table[string, Table[string, string]]]() - - for fleet in fleetJson["fleets"].keys(): - result.fleet[fleet] = initTable[string, Table[string, string]]() - for nodes in fleetJson["fleets"][fleet].keys(): - result.fleet[fleet][nodes] = initTable[string, string]() - for server in fleetJson["fleets"][fleet][nodes].keys(): - result.fleet[fleet][nodes][server] = fleetJson["fleets"][fleet][nodes][server].getStr - - -proc getNodes*(self: FleetConfig, fleet: Fleet, nodeType: FleetNodes = FleetNodes.Bootnodes): seq[string] = - if not self.fleet[$fleet].hasKey($nodeType): return - result = toSeq(self.fleet[$fleet][$nodeType].values) - -proc getMailservers*(self: FleetConfig, fleet: Fleet): Table[string, string] = - if not self.fleet[$fleet].hasKey($FleetNodes.Mailservers): - result = initTable[string,string]() - return - result = self.fleet[$fleet][$FleetNodes.Mailservers] - diff --git a/src/status/types/gas_prediction.nim b/src/status/types/gas_prediction.nim deleted file mode 100644 index 9ce3f16589..0000000000 --- a/src/status/types/gas_prediction.nim +++ /dev/null @@ -1,9 +0,0 @@ -{.used.} - -type GasPricePrediction* = object - safeLow*: float - standard*: float - fast*: float - fastest*: float - currentBaseFee*: float - recommendedBaseFee*: float \ No newline at end of file diff --git a/src/status/types/identity_image.nim b/src/status/types/identity_image.nim deleted file mode 100644 index a77913dcf2..0000000000 --- a/src/status/types/identity_image.nim +++ /dev/null @@ -1,6 +0,0 @@ -{.used.} - -type - IdentityImage* = ref object - thumbnail*: string - large*: string \ No newline at end of file diff --git a/src/status/types/installation.nim b/src/status/types/installation.nim deleted file mode 100644 index 98aff46d11..0000000000 --- a/src/status/types/installation.nim +++ /dev/null @@ -1,14 +0,0 @@ -import json - -type Installation* = ref object - installationId*: string - name*: string - deviceType*: string - enabled*: bool - isUserDevice*: bool - -proc toInstallation*(jsonInstallation: JsonNode): Installation = - result = Installation(installationid: jsonInstallation{"id"}.getStr, enabled: jsonInstallation{"enabled"}.getBool, name: "", deviceType: "", isUserDevice: false) - if jsonInstallation["metadata"].kind != JNull: - result.name = jsonInstallation["metadata"]["name"].getStr - result.deviceType = jsonInstallation["metadata"]["deviceType"].getStr diff --git a/src/status/types/message.nim b/src/status/types/message.nim deleted file mode 100644 index 97ed3981ed..0000000000 --- a/src/status/types/message.nim +++ /dev/null @@ -1,192 +0,0 @@ -{.used.} - -import json, strutils, sequtils, sugar, chronicles -import json_serialization -import ../utils -import ../wallet/account -import ../libstatus/accounts/constants as constants -import ../libstatus/wallet as status_wallet -import ../libstatus/settings as status_settings -import ../libstatus/tokens as status_tokens -import ../libstatus/eth/contracts as status_contracts -import web3/conversions -from ../utils import parseAddress, wei2Eth -import setting, network - -include message_command_parameters -include message_reaction -include message_text_item - -type ContentType* {.pure.} = enum - FetchMoreMessagesButton = -2 - ChatIdentifier = -1, - Unknown = 0, - Message = 1, - Sticker = 2, - Status = 3, - Emoji = 4, - Transaction = 5, - Group = 6, - Image = 7, - Audio = 8 - Community = 9 - Gap = 10 - Edit = 11 - -type Message* = object - alias*: string - userName*: string - localName*: string - chatId*: string - clock*: int - gapFrom*: int - gapTo*: int - commandParameters*: CommandParameters - contentType*: ContentType - ensName*: string - fromAuthor*: string - id*: string - identicon*: string - lineCount*: int - localChatId*: string - messageType*: string # ??? - parsedText*: seq[TextItem] - # quotedMessage: # ??? - replace*: string - responseTo*: string - rtl*: bool # ??? - seen*: bool # ??? - sticker*: string - stickerPackId*: int - text*: string - timestamp*: string - editedAt*: string - whisperTimestamp*: string - isCurrentUser*: bool - stickerHash*: string - outgoingStatus*: string - linkUrls*: string - image*: string - audio*: string - communityId*: string - audioDurationMs*: int - hasMention*: bool - isPinned*: bool - pinnedBy*: string - deleted*: bool - -proc `$`*(self: Message): string = - result = fmt"Message(id:{self.id}, chatId:{self.chatId}, clock:{self.clock}, from:{self.fromAuthor}, contentType:{self.contentType})" - -proc currentUserWalletContainsAddress(address: string): bool = - if (address.len == 0): - return false - - let accounts = status_wallet.getWalletAccounts() - for acc in accounts: - if (acc.address == address): - return true - - return false - -proc toMessage*(jsonMsg: JsonNode): Message = - let publicChatKey = status_settings.getSetting[string](Setting.PublicKey, "0x0") - - var contentType: ContentType - try: - contentType = ContentType(jsonMsg{"contentType"}.getInt) - except: - warn "Unknown content type received", type = jsonMsg{"contentType"}.getInt - contentType = ContentType.Message - - var message = Message( - alias: jsonMsg{"alias"}.getStr, - userName: "", - localName: "", - chatId: jsonMsg{"localChatId"}.getStr, - clock: jsonMsg{"clock"}.getInt, - contentType: contentType, - ensName: jsonMsg{"ensName"}.getStr, - fromAuthor: jsonMsg{"from"}.getStr, - id: jsonMsg{"id"}.getStr, - identicon: jsonMsg{"identicon"}.getStr, - lineCount: jsonMsg{"lineCount"}.getInt, - localChatId: jsonMsg{"localChatId"}.getStr, - messageType: jsonMsg{"messageType"}.getStr, - replace: jsonMsg{"replace"}.getStr, - editedAt: $jsonMsg{"editedAt"}.getInt, - responseTo: jsonMsg{"responseTo"}.getStr, - rtl: jsonMsg{"rtl"}.getBool, - seen: jsonMsg{"seen"}.getBool, - text: jsonMsg{"text"}.getStr, - timestamp: $jsonMsg{"timestamp"}.getInt, - whisperTimestamp: $jsonMsg{"whisperTimestamp"}.getInt, - outgoingStatus: $jsonMsg{"outgoingStatus"}.getStr, - isCurrentUser: publicChatKey == jsonMsg{"from"}.getStr, - stickerHash: "", - stickerPackId: -1, - parsedText: @[], - linkUrls: "", - image: $jsonMsg{"image"}.getStr, - audio: $jsonMsg{"audio"}.getStr, - communityId: $jsonMsg{"communityId"}.getStr, - audioDurationMs: jsonMsg{"audioDurationMs"}.getInt, - deleted: jsonMsg{"deleted"}.getBool, - hasMention: false - ) - - if contentType == ContentType.Gap: - message.gapFrom = jsonMsg["gapParameters"]["from"].getInt - message.gapTo = jsonMsg["gapParameters"]["to"].getInt - - if jsonMsg.contains("parsedText") and jsonMsg{"parsedText"}.kind != JNull: - for text in jsonMsg{"parsedText"}: - message.parsedText.add(text.toTextItem) - - message.linkUrls = concat(message.parsedText.map(t => t.children.filter(c => c.textType == "link"))) - .filter(t => t.destination.startsWith("http") or t.destination.startsWith("statusim://")) - .map(t => t.destination) - .join(" ") - - if message.contentType == ContentType.Sticker: - message.stickerHash = jsonMsg["sticker"]["hash"].getStr - message.stickerPackId = jsonMsg["sticker"]["pack"].getInt - - if message.contentType == ContentType.Transaction: - let - allContracts = getErc20Contracts().concat(getCustomTokens()) - ethereum = newErc20Contract("Ethereum", Network.Mainnet, parseAddress(constants.ZERO_ADDRESS), "ETH", 18, true) - tokenAddress = jsonMsg["commandParameters"]["contract"].getStr - tokenContract = if tokenAddress == "": ethereum else: allContracts.getErc20ContractByAddress(parseAddress(tokenAddress)) - tokenContractStr = if tokenContract == nil: "{}" else: $(Json.encode(tokenContract)) - var weiStr = if tokenContract == nil: "0" else: wei2Eth(jsonMsg["commandParameters"]["value"].getStr, tokenContract.decimals) - weiStr.trimZeros() - - # TODO find a way to use json_seralization for this. When I try, I get an error - message.commandParameters = CommandParameters( - id: jsonMsg["commandParameters"]["id"].getStr, - fromAddress: jsonMsg["commandParameters"]["from"].getStr, - address: jsonMsg["commandParameters"]["address"].getStr, - contract: tokenContractStr, - value: weiStr, - transactionHash: jsonMsg["commandParameters"]["transactionHash"].getStr, - commandState: jsonMsg["commandParameters"]["commandState"].getInt, - signature: jsonMsg["commandParameters"]["signature"].getStr - ) - - # This is kind of a workaround in case we're processing a transaction message. The reason for - # that is a message where a recipient accepted to share his address with sender. In that message - # a recipient's public key is set as a "from" property of a "Message" object and we cannot - # determine which of two users has initiated transaction actually. - # - # To overcome this we're checking if the "from" address from the "commandParameters" object of - # the "Message" is contained as an address in the wallet of logged in user. If yes, means that - # currently logged in user has initiated a transaction (he is a sender), otherwise currently - # logged in user is a recipient. - message.isCurrentUser = currentUserWalletContainsAddress(message.commandParameters.fromAddress) - - message.hasMention = concat(message.parsedText.map( - t => t.children.filter( - c => c.textType == "mention" and c.literal == publicChatKey))).len > 0 - - result = message \ No newline at end of file diff --git a/src/status/types/message_command_parameters.nim b/src/status/types/message_command_parameters.nim deleted file mode 100644 index edb0b3f216..0000000000 --- a/src/status/types/message_command_parameters.nim +++ /dev/null @@ -1,16 +0,0 @@ -{.used.} - -import strformat - -type CommandParameters* = object - id*: string - fromAddress*: string - address*: string - contract*: string - value*: string - transactionHash*: string - commandState*: int - signature*: string - -proc `$`*(self: CommandParameters): string = - result = fmt"CommandParameters(id:{self.id}, fromAddr:{self.fromAddress}, addr:{self.address}, contract:{self.contract}, value:{self.value}, transactionHash:{self.transactionHash}, commandState:{self.commandState}, signature:{self.signature})" \ No newline at end of file diff --git a/src/status/types/message_reaction.nim b/src/status/types/message_reaction.nim deleted file mode 100644 index f554aa3140..0000000000 --- a/src/status/types/message_reaction.nim +++ /dev/null @@ -1,21 +0,0 @@ -{.used.} - -import json - -type Reaction* = object - id*: string - chatId*: string - fromAccount*: string - messageId*: string - emojiId*: int - retracted*: bool - -proc toReaction*(jsonReaction: JsonNode): Reaction = - result = Reaction( - id: jsonReaction{"id"}.getStr, - chatId: jsonReaction{"chatId"}.getStr, - fromAccount: jsonReaction{"from"}.getStr, - messageId: jsonReaction{"messageId"}.getStr, - emojiId: jsonReaction{"emojiId"}.getInt, - retracted: jsonReaction{"retracted"}.getBool - ) \ No newline at end of file diff --git a/src/status/types/message_text_item.nim b/src/status/types/message_text_item.nim deleted file mode 100644 index 210ea49075..0000000000 --- a/src/status/types/message_text_item.nim +++ /dev/null @@ -1,25 +0,0 @@ -{.used.} - -import json, strutils - -type TextItem* = object - textType*: string - children*: seq[TextItem] - literal*: string - destination*: string - -proc toTextItem*(jsonText: JsonNode): TextItem = - result = TextItem( - literal: jsonText{"literal"}.getStr, - textType: jsonText{"type"}.getStr, - destination: jsonText{"destination"}.getStr, - children: @[] - ) - if (result.literal.startsWith("statusim://")): - result.textType = "link" - # TODO isolate the link only - result.destination = result.literal - - if jsonText.hasKey("children") and jsonText["children"].kind != JNull: - for child in jsonText["children"]: - result.children.add(child.toTextItem) \ No newline at end of file diff --git a/src/status/types/multi_accounts.nim b/src/status/types/multi_accounts.nim deleted file mode 100644 index f11871230f..0000000000 --- a/src/status/types/multi_accounts.nim +++ /dev/null @@ -1,12 +0,0 @@ -{.used.} - -import json_serialization -import ../libstatus/accounts/constants - -include derived_account - -type MultiAccounts* = object - whisper* {.serializedFieldName(PATH_WHISPER).}: DerivedAccount - walletRoot* {.serializedFieldName(PATH_WALLET_ROOT).}: DerivedAccount - defaultWallet* {.serializedFieldName(PATH_DEFAULT_WALLET).}: DerivedAccount - eip1581* {.serializedFieldName(PATH_EIP_1581).}: DerivedAccount \ No newline at end of file diff --git a/src/status/types/network.nim b/src/status/types/network.nim deleted file mode 100644 index ddd37b7a48..0000000000 --- a/src/status/types/network.nim +++ /dev/null @@ -1,15 +0,0 @@ -{.used.} - -include node_config -include network_details -include upstream_config - -type - Network* {.pure.} = enum - Mainnet = "mainnet_rpc", - Testnet = "testnet_rpc", - Rinkeby = "rinkeby_rpc", - Goerli = "goerli_rpc", - XDai = "xdai_rpc", - Poa = "poa_rpc", - Other = "other" \ No newline at end of file diff --git a/src/status/types/network_details.nim b/src/status/types/network_details.nim deleted file mode 100644 index 6e4aeb7bb6..0000000000 --- a/src/status/types/network_details.nim +++ /dev/null @@ -1,12 +0,0 @@ -{.used.} - -import json_serialization - -import node_config - -type - NetworkDetails* = ref object - id*: string - name*: string - etherscanLink* {.serializedFieldName("etherscan-link").}: string - config*: NodeConfig diff --git a/src/status/types/node_config.nim b/src/status/types/node_config.nim deleted file mode 100644 index c266e326e4..0000000000 --- a/src/status/types/node_config.nim +++ /dev/null @@ -1,11 +0,0 @@ -{.used.} - -import json_serialization - -import upstream_config - -type - NodeConfig* = ref object - networkId* {.serializedFieldName("NetworkId").}: int - dataDir* {.serializedFieldName("DataDir").}: string - upstreamConfig* {.serializedFieldName("UpstreamConfig").}: UpstreamConfig \ No newline at end of file diff --git a/src/status/types/os_notification.nim b/src/status/types/os_notification.nim deleted file mode 100644 index e9eda5e8ad..0000000000 --- a/src/status/types/os_notification.nim +++ /dev/null @@ -1,46 +0,0 @@ -{.used.} - -import json - -import ../../eventemitter - -type - OsNotificationType* {.pure.} = enum - NewContactRequest = 1, - AcceptedContactRequest, - JoinCommunityRequest, - AcceptedIntoCommunity, - RejectedByCommunity, - NewMessage - - OsNotificationDetails* = object - notificationType*: OsNotificationType - communityId*: string - channelId*: string - messageId*: string - -type - OsNotificationsArgs* = ref object of Args - details*: OsNotificationDetails - -proc toOsNotificationDetails*(json: JsonNode): OsNotificationDetails = - if (not (json.contains("notificationType") and - json.contains("communityId") and - json.contains("channelId") and - json.contains("messageId"))): - return OsNotificationDetails() - - return OsNotificationDetails( - notificationType: json{"notificationType"}.getInt.OsNotificationType, - communityId: json{"communityId"}.getStr, - channelId: json{"channelId"}.getStr, - messageId: json{"messageId"}.getStr - ) - -proc toJsonNode*(self: OsNotificationDetails): JsonNode = - result = %* { - "notificationType": self.notificationType.int, - "communityId": self.communityId, - "channelId": self.channelId, - "messageId": self.messageId - } \ No newline at end of file diff --git a/src/status/types/pending_transaction_type.nim b/src/status/types/pending_transaction_type.nim deleted file mode 100644 index fa094a5b7f..0000000000 --- a/src/status/types/pending_transaction_type.nim +++ /dev/null @@ -1,8 +0,0 @@ -{.used.} - -type PendingTransactionType* {.pure.} = enum - RegisterENS = "RegisterENS", - SetPubKey = "SetPubKey", - ReleaseENS = "ReleaseENS", - BuyStickerPack = "BuyStickerPack" - WalletTransfer = "WalletTransfer" diff --git a/src/status/types/profile.nim b/src/status/types/profile.nim deleted file mode 100644 index 540bf37b33..0000000000 --- a/src/status/types/profile.nim +++ /dev/null @@ -1,49 +0,0 @@ -{.used.} - -import json, strformat -import identity_image - -export identity_image - -type Profile* = ref object - id*, alias*, username*, identicon*, address*, ensName*, localNickname*: string - ensVerified*: bool - messagesFromContactsOnly*: bool - sendUserStatus*: bool - currentUserStatus*: int - identityImage*: IdentityImage - appearance*: int - systemTags*: seq[string] - -proc `$`*(self: Profile): string = - return fmt"Profile(id:{self.id}, username:{self.username})" - -proc toProfileModel*(profile: JsonNode): Profile = - var systemTags: seq[string] = @[] - if profile["systemTags"].kind != JNull: - systemTags = profile["systemTags"].to(seq[string]) - - result = Profile( - id: profile["id"].str, - username: profile["alias"].str, - identicon: profile["identicon"].str, - identityImage: IdentityImage(), - address: profile["id"].str, - alias: profile["alias"].str, - ensName: "", - ensVerified: profile["ensVerified"].getBool, - appearance: 0, - systemTags: systemTags - ) - - if profile.hasKey("name"): - result.ensName = profile["name"].str - - if profile.hasKey("localNickname"): - result.localNickname = profile["localNickname"].str - - if profile.hasKey("images") and profile["images"].kind != JNull: - if profile["images"].hasKey("thumbnail"): - result.identityImage.thumbnail = profile["images"]["thumbnail"]["uri"].str - if profile["images"].hasKey("large"): - result.identityImage.large = profile["images"]["large"]["uri"].str \ No newline at end of file diff --git a/src/status/types/removed_message.nim b/src/status/types/removed_message.nim deleted file mode 100644 index dffab11e50..0000000000 --- a/src/status/types/removed_message.nim +++ /dev/null @@ -1,13 +0,0 @@ -{.used.} - -import json - -type RemovedMessage* = object - chatId*: string - messageId*: string - -proc toRemovedMessage*(jsonRemovedMessage: JsonNode): RemovedMessage = - result = RemovedMessage( - chatId: jsonRemovedMessage{"chatId"}.getStr, - messageId: jsonRemovedMessage{"messageId"}.getStr, - ) \ No newline at end of file diff --git a/src/status/types/rpc_response.nim b/src/status/types/rpc_response.nim deleted file mode 100644 index 9a6e30b430..0000000000 --- a/src/status/types/rpc_response.nim +++ /dev/null @@ -1,29 +0,0 @@ -{.used.} - -type - RpcError* = ref object - code*: int - message*: string - -type - RpcResponse* = ref object - jsonrpc*: string - result*: string - id*: int - error*: RpcError - - # TODO: replace all RpcResponse and RpcResponseTyped occurances with a generic - # form of RpcReponse. IOW, rename RpceResponseTyped*[T] to RpcResponse*[T] and - # remove RpcResponse. -type - RpcResponseTyped*[T] = object - jsonrpc*: string - result*: T - id*: int - error*: RpcError - -type - StatusGoException* = object of CatchableError - -type - RpcException* = object of CatchableError \ No newline at end of file diff --git a/src/status/types/setting.nim b/src/status/types/setting.nim deleted file mode 100644 index 123f58b593..0000000000 --- a/src/status/types/setting.nim +++ /dev/null @@ -1,31 +0,0 @@ -{.used.} - -type - Setting* {.pure.} = enum - Appearance = "appearance", - Bookmarks = "bookmarks", - Currency = "currency" - EtherscanLink = "etherscan-link" - InstallationId = "installation-id" - MessagesFromContactsOnly = "messages-from-contacts-only" - Mnemonic = "mnemonic" - Networks_Networks = "networks/networks" - Networks_CurrentNetwork = "networks/current-network" - NodeConfig = "node-config" - PublicKey = "public-key" - DappsAddress = "dapps-address" - Stickers_PacksInstalled = "stickers/packs-installed" - Stickers_Recent = "stickers/recent-stickers" - Gifs_Recent = "gifs/recent-gifs" - Gifs_Favorite = "gifs/favorite-gifs" - WalletRootAddress = "wallet-root-address" - LatestDerivedPath = "latest-derived-path" - PreferredUsername = "preferred-name" - Usernames = "usernames" - SigningPhrase = "signing-phrase" - Fleet = "fleet" - VisibleTokens = "wallet/visible-tokens" - PinnedMailservers = "pinned-mailservers" - WakuBloomFilterMode = "waku-bloom-filter-mode" - SendUserStatus = "send-status-updates?" - CurrentUserStatus = "current-user-status" \ No newline at end of file diff --git a/src/status/types/status_update.nim b/src/status/types/status_update.nim deleted file mode 100644 index 56c084f466..0000000000 --- a/src/status/types/status_update.nim +++ /dev/null @@ -1,24 +0,0 @@ -{.used.} - -import json - -type StatusUpdateType* {.pure.}= enum - Unknown = 0, - Online = 1, - DoNotDisturb = 2 - -type StatusUpdate* = object - publicKey*: string - statusType*: StatusUpdateType - clock*: uint64 - text*: string - -proc toStatusUpdate*(jsonStatusUpdate: JsonNode): StatusUpdate = - let statusTypeInt = jsonStatusUpdate{"statusType"}.getInt - let statusType: StatusUpdateType = if statusTypeInt >= ord(low(StatusUpdateType)) or statusTypeInt <= ord(high(StatusUpdateType)): StatusUpdateType(statusTypeInt) else: StatusUpdateType.Unknown - result = StatusUpdate( - publicKey: jsonStatusUpdate{"publicKey"}.getStr, - statusType: statusType, - clock: uint64(jsonStatusUpdate{"clock"}.getBiggestInt), - text: jsonStatusUpdate{"text"}.getStr - ) \ No newline at end of file diff --git a/src/status/types/sticker.nim b/src/status/types/sticker.nim deleted file mode 100644 index 62055c47e7..0000000000 --- a/src/status/types/sticker.nim +++ /dev/null @@ -1,32 +0,0 @@ -{.used.} - -import json, options, typetraits -import web3/ethtypes, json_serialization, stint - -type Sticker* = object - hash*: string - packId*: int - -type StickerPack* = object - author*: string - id*: int - name*: string - price*: Stuint[256] - preview*: string - stickers*: seq[Sticker] - thumbnail*: string - -proc `%`*(stuint256: Stuint[256]): JsonNode = - newJString($stuint256) - -proc readValue*(reader: var JsonReader, value: var Stuint[256]) - {.raises: [IOError, SerializationError, Defect].} = - try: - let strVal = reader.readValue(string) - value = strVal.parse(Stuint[256]) - except: - try: - let intVal = reader.readValue(int) - value = intVal.stuint(256) - except: - raise newException(SerializationError, "Expected string or int representation of Stuint[256]") \ No newline at end of file diff --git a/src/status/types/transaction.nim b/src/status/types/transaction.nim deleted file mode 100644 index d86d77db28..0000000000 --- a/src/status/types/transaction.nim +++ /dev/null @@ -1,30 +0,0 @@ -{.used.} - -import strutils - -include pending_transaction_type - -type - Transaction* = ref object - id*: string - typeValue*: string - address*: string - blockNumber*: string - blockHash*: string - contract*: string - timestamp*: string - gasPrice*: string - gasLimit*: string - gasUsed*: string - nonce*: string - txStatus*: string - value*: string - fromAddress*: string - to*: string - -proc cmpTransactions*(x, y: Transaction): int = - # Sort proc to compare transactions from a single account. - # Compares first by block number, then by nonce - result = cmp(x.blockNumber.parseHexInt, y.blockNumber.parseHexInt) - if result == 0: - result = cmp(x.nonce, y.nonce) \ No newline at end of file diff --git a/src/status/types/upstream_config.nim b/src/status/types/upstream_config.nim deleted file mode 100644 index 81a513f5de..0000000000 --- a/src/status/types/upstream_config.nim +++ /dev/null @@ -1,8 +0,0 @@ -{.used.} - -import json_serialization - -type - UpstreamConfig* = ref object - enabled* {.serializedFieldName("Enabled").}: bool - url* {.serializedFieldName("URL").}: string \ No newline at end of file diff --git a/src/status/updates.nim b/src/status/updates.nim deleted file mode 100644 index 3868f13512..0000000000 --- a/src/status/updates.nim +++ /dev/null @@ -1,44 +0,0 @@ -import ens, provider -import stew/byteutils -from base32 import nil -import chronicles, httpclient, net -import nbaser, strutils -import semver -import constants - - -type - VersionInfo* = object - version*: string - url*: string - -proc getLatestVersion*(): VersionInfo = - let contentHash = contenthash(APP_UPDATES_ENS) - if contentHash == "": - raise newException(ValueError, "ENS does not have a content hash") - - var url: string = "" - - let decodedHash = contentHash.decodeENSContentHash() - case decodedHash[0]: - of ENSType.IPFS: - let base32Hash = base32.encode(string.fromBytes(base58.decode(decodedHash[1]))).toLowerAscii().replace("=", "") - url = "https://" & base32Hash & IPFS_GATEWAY - of ENSType.SWARM: - url = "https://" & SWARM_GATEWAY & "/bzz:/" & decodedHash[1] - of ENSType.IPNS: - url = "https://" & decodedHash[1] - else: - warn "Unknown content for", contentHash - raise newException(ValueError, "Unknown content for " & contentHash) - - # Read version from folder - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext, timeout = CHECK_VERSION_TIMEOUT_MS) - result.version = client.getContent(url & "/VERSION").strip() - result.url = url - -proc isNewer*(currentVersion, versionToCheck: string): bool = - let lastVersion = parseVersion(versionToCheck) - let currVersion = parseVersion(currentVersion) - result = lastVersion > currVersion diff --git a/src/status/utils.nim b/src/status/utils.nim deleted file mode 100644 index d0720a08c9..0000000000 --- a/src/status/utils.nim +++ /dev/null @@ -1,178 +0,0 @@ -import json, random, strutils, strformat, tables, chronicles, unicode, times -from sugar import `=>`, `->` -import stint -from times import getTime, toUnix, nanosecond -import libstatus/accounts/signing_phrases -from web3 import Address, fromHex -import web3/ethhexstrings - -proc getTimelineChatId*(pubKey: string = ""): string = - if pubKey == "": - return "@timeline70bd746ddcc12beb96b2c9d572d0784ab137ffc774f5383e50585a932080b57cca0484b259e61cecbaa33a4c98a300a" - else: - return "@" & pubKey - -proc isWakuEnabled(): bool = - true # TODO: - -proc prefix*(methodName: string, isExt:bool = true): string = - result = if isWakuEnabled(): "waku" else: "shh" - result = result & (if isExt: "ext_" else: "_") - result = result & methodName - -proc isOneToOneChat*(chatId: string): bool = - result = chatId.startsWith("0x") # There is probably a better way to do this - -proc keys*(obj: JsonNode): seq[string] = - result = newSeq[string]() - for k, _ in obj: - result.add k - -proc generateSigningPhrase*(count: int): string = - let now = getTime() - var rng = initRand(now.toUnix * 1000000000 + now.nanosecond) - var phrases: seq[string] = @[] - - for i in 1..count: - phrases.add(rng.sample(signing_phrases.phrases)) - - result = phrases.join(" ") - -proc handleRPCErrors*(response: string) = - let parsedReponse = parseJson(response) - if (parsedReponse.hasKey("error")): - raise newException(ValueError, parsedReponse["error"]["message"].str) - -proc toStUInt*[bits: static[int]](flt: float, T: typedesc[StUint[bits]]): T = - var stringValue = fmt"{flt:<.0f}" - stringValue.removeSuffix('.') - if (flt >= 0): - result = parse($stringValue, StUint[bits]) - else: - result = parse("0", StUint[bits]) - -proc toUInt256*(flt: float): UInt256 = - toStUInt(flt, StUInt[256]) - -proc toUInt64*(flt: float): StUInt[64] = - toStUInt(flt, StUInt[64]) - -proc eth2Wei*(eth: float, decimals: int = 18): UInt256 = - let weiValue = eth * parseFloat(alignLeft("1", decimals + 1, '0')) - weiValue.toUInt256 - -proc gwei2Wei*(gwei: float): UInt256 = - eth2Wei(gwei, 9) - -proc wei2Eth*(input: Stuint[256], decimals: int = 18): string = - var one_eth = u256(10).pow(decimals) # fromHex(Stuint[256], "DE0B6B3A7640000") - - var (eth, remainder) = divmod(input, one_eth) - let leading_zeros = "0".repeat(($one_eth).len - ($remainder).len - 1) - - fmt"{eth}.{leading_zeros}{remainder}" - -proc wei2Eth*(input: string, decimals: int): string = - try: - var input256: Stuint[256] - if input.contains("e+"): # we have a js string BN, ie 1e+21 - let - inputSplit = input.split("e+") - whole = inputSplit[0].u256 - remainder = u256(10).pow(inputSplit[1].parseInt) - input256 = whole * remainder - else: - input256 = input.u256 - result = wei2Eth(input256, decimals) - except Exception as e: - error "Error parsing this wei value", input, msg=e.msg - result = "0" - - -proc first*(jArray: JsonNode, fieldName, id: string): JsonNode = - if jArray == nil: - return nil - if jArray.kind != JArray: - raise newException(ValueError, "Parameter 'jArray' is a " & $jArray.kind & ", but must be a JArray") - for child in jArray.getElems: - if child{fieldName}.getStr.toLower == id.toLower: - return child - -proc any*(jArray: JsonNode, fieldName, id: string): bool = - if jArray == nil: - return false - result = false - for child in jArray.getElems: - if child{fieldName}.getStr.toLower == id.toLower: - return true - -proc isEmpty*(a: JsonNode): bool = - case a.kind: - of JObject: return a.fields.len == 0 - of JArray: return a.elems.len == 0 - of JString: return a.str == "" - of JNull: return true - else: - return false - -proc find*[T](s: seq[T], pred: proc(x: T): bool {.closure.}): T {.inline.} = - let results = s.filter(pred) - if results.len == 0: - return default(type(T)) - result = results[0] - -proc find*[T](s: seq[T], pred: proc(x: T): bool {.closure.}, found: var bool): T {.inline.} = - let results = s.filter(pred) - if results.len == 0: - found = false - return default(type(T)) - result = results[0] - found = true - -proc parseAddress*(strAddress: string): Address = - fromHex(Address, strAddress) - -proc isAddress*(strAddress: string): bool = - try: - discard parseAddress(strAddress) - except: - return false - return true - -proc validateTransactionInput*(from_addr, to_addr, assetAddress, value, gas, gasPrice, data, uuid: string) = - if not isAddress(from_addr): raise newException(ValueError, "from_addr is not a valid ETH address") - if not isAddress(to_addr): raise newException(ValueError, "to_addr is not a valid ETH address") - if parseFloat(value) < 0: raise newException(ValueError, "value should be a number >= 0") - if parseInt(gas) <= 0: raise newException(ValueError, "gas should be a number > 0") - if parseFloat(gasPrice) <= 0: raise newException(ValueError, "gasPrice should be a number > 0") - - if uuid.isEmptyOrWhitespace(): raise newException(ValueError, "uuid is required") - - if assetAddress != "": # If a token is being used - if not isAddress(assetAddress): raise newException(ValueError, "assetAddress is not a valid ETH address") - if assetAddress == "0x0000000000000000000000000000000000000000": raise newException(ValueError, "assetAddress requires a valid token address") - - if data != "": # If data is being used - if not validate(HexDataStr(data)): raise newException(ValueError, "data should contain a valid hex string") - -proc hex2Time*(hex: string): Time = - # represents the time since 1970-01-01T00:00:00Z - fromUnix(fromHex[int64](hex)) - -proc hex2LocalDateTime*(hex: string): DateTime = - # Convert hex time (since 1970-01-01T00:00:00Z) into a DateTime using the - # local timezone. - hex.hex2Time.local - -proc isUnique*[T](key: T, existingKeys: var seq[T]): bool = - # If the key doesn't exist in the existingKeys seq, add it and return true. - # Otherwise, the key already existed, so return false. - # Can be used to deduplicate sequences with `deduplicate[T]`. - if not existingKeys.contains(key): - existingKeys.add key - return true - return false - -proc deduplicate*[T](txs: var seq[T], key: (T) -> string) = - var existingKeys: seq[string] = @[] - txs.keepIf(tx => tx.key().isUnique(existingKeys)) diff --git a/src/status/utils/cache.nim b/src/status/utils/cache.nim deleted file mode 100644 index 566c6f4aed..0000000000 --- a/src/status/utils/cache.nim +++ /dev/null @@ -1,17 +0,0 @@ -import tables, times - -type ValueTime* = ref object - value*: string - timestamp*: DateTime - -type CachedValues* = Table[string, ValueTime] - -proc newCachedValues*(): CachedValues = initTable[string, ValueTime]() - -proc isCached*(self: CachedValues, cacheKey: string, duration=initDuration(minutes = 5)): bool = - self.hasKey(cacheKey) and ((self[cacheKey].timestamp + duration) >= now()) - -proc cacheValue*(self: var CachedValues, cacheKey: string, value: string) = - self[cacheKey] = ValueTime(value: value, timestamp: now()) - -proc get*(self: var CachedValues, cacheKey: string): string = self[cacheKey].value diff --git a/src/status/utils/json_utils.nim b/src/status/utils/json_utils.nim deleted file mode 100644 index 6ca96d66e6..0000000000 --- a/src/status/utils/json_utils.nim +++ /dev/null @@ -1,33 +0,0 @@ -import json - -template getProp(obj: JsonNode, prop: string, value: var typedesc[int]): bool = - var success = false - if (obj.kind == JObject and obj.contains(prop)): - value = obj[prop].getInt - success = true - - success - -template getProp(obj: JsonNode, prop: string, value: var typedesc[string]): bool = - var success = false - if (obj.kind == JObject and obj.contains(prop)): - value = obj[prop].getStr - success = true - - success - -template getProp(obj: JsonNode, prop: string, value: var typedesc[float]): bool = - var success = false - if (obj.kind == JObject and obj.contains(prop)): - value = obj[prop].getFloat - success = true - - success - -template getProp(obj: JsonNode, prop: string, value: var typedesc[JsonNode]): bool = - var success = false - if (obj.kind == JObject and obj.contains(prop)): - value = obj[prop] - success = true - - success \ No newline at end of file diff --git a/src/status/wallet.nim b/src/status/wallet.nim deleted file mode 100644 index 9a62b8c8fc..0000000000 --- a/src/status/wallet.nim +++ /dev/null @@ -1,408 +0,0 @@ -import json, strformat, strutils, chronicles, sequtils, sugar, httpclient, tables, net -import json_serialization, stint -from web3/ethtypes import Address, EthSend, Quantity -from web3/conversions import `$` -from libstatus/core import getBlockByNumber -import libstatus/accounts as status_accounts -import libstatus/tokens as status_tokens -import libstatus/settings as status_settings -import libstatus/wallet as status_wallet -import libstatus/accounts/constants as constants -import libstatus/eth/[eth, contracts] -from libstatus/core import getBlockByNumber -from utils as libstatus_utils import eth2Wei, gwei2Wei, first, toUInt64, parseAddress -import wallet/[balance_manager, collectibles] -import wallet/account as wallet_account -import transactions -import ../eventemitter -import options -import ./types/[account, transaction, network, setting, gas_prediction, rpc_response] -export wallet_account, collectibles -export Transaction - -logScope: - topics = "wallet-model" - -proc confirmed*(self:PendingTransactionType):string = - result = "transaction:" & $self - -type TransactionMinedArgs* = ref object of Args - data*: string - transactionHash*: string - success*: bool - revertReason*: string # TODO: possible to get revert reason in here? - -type WalletModel* = ref object - events*: EventEmitter - accounts*: seq[WalletAccount] - defaultCurrency*: string - tokens*: seq[Erc20Contract] - totalBalance*: float - -proc getDefaultCurrency*(self: WalletModel): string -proc calculateTotalFiatBalance*(self: WalletModel) - -proc newWalletModel*(events: EventEmitter): WalletModel = - result = WalletModel() - result.accounts = @[] - result.tokens = @[] - result.events = events - result.defaultCurrency = "" - result.totalBalance = 0.0 - -proc initEvents*(self: WalletModel) = - self.events.on("currencyChanged") do(e: Args): - self.defaultCurrency = self.getDefaultCurrency() - for account in self.accounts: - updateBalance(account, self.getDefaultCurrency()) - self.calculateTotalFiatBalance() - self.events.emit("accountsUpdated", Args()) - - self.events.on("newAccountAdded") do(e: Args): - self.calculateTotalFiatBalance() - -proc delete*(self: WalletModel) = - discard - -proc buildTokenTransaction(source, to, assetAddress: Address, value: float, transfer: var Transfer, contract: var Erc20Contract, gas = "", gasPrice = ""): EthSend = - contract = getErc20Contract(assetAddress) - if contract == nil: - raise newException(ValueError, fmt"Could not find ERC-20 contract with address '{assetAddress}' for the current network") - transfer = Transfer(to: to, value: eth2Wei(value, contract.decimals)) - transactions.buildTokenTransaction(source, assetAddress, gas, gasPrice) - -proc getKnownTokenContract*(self: WalletModel, address: Address): Erc20Contract = - getErc20Contracts().concat(getCustomTokens()).getErc20ContractByAddress(address) - -proc estimateGas*(self: WalletModel, source, to, value, data: string, success: var bool): string = - var tx = transactions.buildTransaction( - parseAddress(source), - eth2Wei(parseFloat(value), 18), - data = data - ) - tx.to = parseAddress(to).some - result = eth.estimateGas(tx, success) - -proc getTransactionReceipt*(self: WalletModel, transactionHash: string): JsonNode = - result = status_wallet.getTransactionReceipt(transactionHash).parseJSON()["result"] - -proc confirmTransactionStatus(self: WalletModel, pendingTransactions: JsonNode, blockNumber: int) = - for trx in pendingTransactions.getElems(): - let transactionReceipt = self.getTransactionReceipt(trx["hash"].getStr) - if transactionReceipt.kind != JNull: - status_wallet.deletePendingTransaction(trx["hash"].getStr) - let ev = TransactionMinedArgs( - data: trx["additionalData"].getStr, - transactionHash: trx["hash"].getStr, - success: transactionReceipt{"status"}.getStr == "0x1", - revertReason: "" - ) - self.events.emit(parseEnum[PendingTransactionType](trx["type"].getStr).confirmed, ev) - -proc getLatestBlockNumber*(self: WalletModel): int = - let response = getBlockByNumber("latest").parseJson() - if not response.hasKey("result"): - return -1 - - return parseInt($fromHex(Stuint[256], response["result"]["number"].getStr)) - -proc checkPendingTransactions*(self: WalletModel) = - let latestBlockNumber = self.getLatestBlockNumber() - if latestBlockNumber == -1: - return - - let pendingTransactions = status_wallet.getPendingTransactions() - if (pendingTransactions != ""): - self.confirmTransactionStatus(pendingTransactions.parseJson{"result"}, latestBlockNumber) - -proc checkPendingTransactions*(self: WalletModel, address: string, blockNumber: int) = - self.confirmTransactionStatus(status_wallet.getPendingOutboundTransactionsByAddress(address).parseJson["result"], blockNumber) - -proc estimateTokenGas*(self: WalletModel, source, to, assetAddress, value: string, success: var bool): string = - var - transfer: Transfer - contract: Erc20Contract - tx = buildTokenTransaction( - parseAddress(source), - parseAddress(to), - parseAddress(assetAddress), - parseFloat(value), - transfer, - contract - ) - - result = contract.methods["transfer"].estimateGas(tx, transfer, success) - -proc sendTransaction*(source, to, value, gas, gasPrice, password: string, success: var bool, data = ""): string = - var tx = transactions.buildTransaction( - parseAddress(source), - eth2Wei(parseFloat(value), 18), gas, gasPrice, data - ) - - if to != "": - tx.to = parseAddress(to).some - - result = eth.sendTransaction(tx, password, success) - if success: - trackPendingTransaction(result, $source, $to, PendingTransactionType.WalletTransfer, "") - -proc sendTokenTransaction*(source, to, assetAddress, value, gas, gasPrice, password: string, success: var bool): string = - var - transfer: Transfer - contract: Erc20Contract - tx = buildTokenTransaction( - parseAddress(source), - parseAddress(to), - parseAddress(assetAddress), - parseFloat(value), - transfer, - contract, - gas, - gasPrice - ) - - result = contract.methods["transfer"].send(tx, transfer, password, success) - if success: - trackPendingTransaction(result, $source, $to, PendingTransactionType.WalletTransfer, "") - -proc getDefaultCurrency*(self: WalletModel): string = - # TODO: this should come from a model? It is going to be used too in the - # profile section and ideally we should not call the settings more than once - status_settings.getSetting[string](Setting.Currency, "usd") - -# TODO: This needs to be removed or refactored so that test tokens are shown -# when on testnet https://github.com/status-im/nim-status-client/issues/613. -proc getStatusToken*(self: WalletModel): string = - var - token = Asset() - erc20Contract = getSntContract() - token.name = erc20Contract.name - token.symbol = erc20Contract.symbol - token.address = $erc20Contract.address - result = $(%token) - -proc setDefaultCurrency*(self: WalletModel, currency: string) = - discard status_settings.saveSetting(Setting.Currency, currency) - self.events.emit("currencyChanged", CurrencyArgs(currency: currency)) - -proc generateAccountConfiguredAssets*(self: WalletModel, accountAddress: string): seq[Asset] = - var assets: seq[Asset] = @[] - var asset = Asset(name:"Ethereum", symbol: "ETH", value: "0.0", fiatBalanceDisplay: "0.0", accountAddress: accountAddress) - assets.add(asset) - for token in self.tokens: - var symbol = token.symbol - var existingToken = Asset(name: token.name, symbol: symbol, value: fmt"0.0", fiatBalanceDisplay: "$0.0", accountAddress: accountAddress, address: $token.address) - assets.add(existingToken) - assets - -proc populateAccount*(self: WalletModel, walletAccount: var WalletAccount, balance: string, refreshCache: bool = false) = - var assets: seq[Asset] = self.generateAccountConfiguredAssets(walletAccount.address) - walletAccount.balance = none[string]() - walletAccount.assetList = assets - walletAccount.realFiatBalance = none[float]() - -proc update*(self: WalletModel, address: string, ethBalance: string, tokens: JsonNode) = - for account in self.accounts: - if account.address != address: continue - storeBalances(account, ethBalance, tokens) - updateBalance(account, self.getDefaultCurrency(), false) - -proc getEthBalance*(address: string): string = - var balance = getBalance(address) - result = hex2token(balance, 18) - -proc newAccount*(self: WalletModel, walletType: string, derivationPath: string, name: string, address: string, iconColor: string, balance: string, publicKey: string): WalletAccount = - var assets: seq[Asset] = self.generateAccountConfiguredAssets(address) - var account = WalletAccount(name: name, path: derivationPath, walletType: walletType, address: address, iconColor: iconColor, balance: none[string](), assetList: assets, realFiatBalance: none[float](), publicKey: publicKey) - updateBalance(account, self.getDefaultCurrency()) - account - -proc initAccounts*(self: WalletModel) = - self.tokens = status_tokens.getVisibleTokens() - let accounts = status_wallet.getWalletAccounts() - for account in accounts: - var acc = WalletAccount(account) - self.populateAccount(acc, "") - updateBalance(acc, self.getDefaultCurrency(), true) - self.accounts.add(acc) - -proc updateAccount*(self: WalletModel, address: string) = - for acc in self.accounts.mitems: - if acc.address == address: - self.populateAccount(acc, "", true) - updateBalance(acc, self.getDefaultCurrency(), true) - self.events.emit("accountsUpdated", Args()) - -proc getTotalFiatBalance*(self: WalletModel): string = - self.calculateTotalFiatBalance() - fmt"{self.totalBalance:.2f}" - -proc convertValue*(self: WalletModel, balance: string, fromCurrency: string, toCurrency: string): float = - result = convertValue(balance, fromCurrency, toCurrency) - -proc calculateTotalFiatBalance*(self: WalletModel) = - self.totalBalance = 0.0 - for account in self.accounts: - if account.realFiatBalance.isSome: - self.totalBalance += account.realFiatBalance.get() - -proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true, walletIndex: int = 0) = - try: - generatedAccount.name = accountName - var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount, walletIndex) - var account = self.newAccount(accountType, derivedAccount.derivationPath, accountName, derivedAccount.address, color, fmt"0.00 {self.defaultCurrency}", derivedAccount.publicKey) - self.accounts.add(account) - # wallet_checkRecentHistory is required to be called when a new account is - # added before wallet_getTransfersByAddress can be called. This is because - # wallet_checkRecentHistory populates the status-go db that - # wallet_getTransfersByAddress reads from - discard status_wallet.checkRecentHistory(self.accounts.map(account => account.address)) - self.events.emit("newAccountAdded", wallet_account.AccountArgs(account: account)) - except Exception as e: - raise newException(StatusGoException, fmt"Error adding new account: {e.msg}") - -proc generateNewAccount*(self: WalletModel, password: string, accountName: string, color: string) = - let - walletRootAddress = status_settings.getSetting[string](Setting.WalletRootAddress, "") - walletIndex = status_settings.getSetting[int](Setting.LatestDerivedPath) + 1 - loadedAccount = status_accounts.loadAccount(walletRootAddress, password) - derivedAccount = status_accounts.deriveWallet(loadedAccount.id, walletIndex) - generatedAccount = GeneratedAccount( - id: loadedAccount.id, - publicKey: derivedAccount.publicKey, - address: derivedAccount.address - ) - - # if we've gotten here, the password is ok (loadAccount requires a valid password) - # so no need to check for a valid password - self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.GENERATED, true, walletIndex) - - let statusGoResult = status_settings.saveSetting(Setting.LatestDerivedPath, $walletIndex) - if statusGoResult.error != "": - error "Error storing the latest wallet index", msg=statusGoResult.error - -proc addAccountsFromSeed*(self: WalletModel, seed: string, password: string, accountName: string, color: string) = - let mnemonic = replace(seed, ',', ' ') - var generatedAccount = status_accounts.multiAccountImportMnemonic(mnemonic) - generatedAccount.derived = status_accounts.deriveAccounts(generatedAccount.id) - - let - defaultAccount = status_accounts.getDefaultAccount() - isPasswordOk = status_accounts.verifyAccountPassword(defaultAccount, password) - if not isPasswordOk: - raise newException(StatusGoException, "Error generating new account: invalid password") - - self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.SEED) - -proc addAccountsFromPrivateKey*(self: WalletModel, privateKey: string, password: string, accountName: string, color: string) = - let - generatedAccount = status_accounts.MultiAccountImportPrivateKey(privateKey) - defaultAccount = status_accounts.getDefaultAccount() - isPasswordOk = status_accounts.verifyAccountPassword(defaultAccount, password) - - if not isPasswordOk: - raise newException(StatusGoException, "Error generating new account: invalid password") - - self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.KEY, false) - -proc addWatchOnlyAccount*(self: WalletModel, address: string, accountName: string, color: string) = - let account = GeneratedAccount(address: address) - self.addNewGeneratedAccount(account, "", accountName, color, constants.WATCH, false) - -proc hasAsset*(self: WalletModel, symbol: string): bool = - self.tokens.anyIt(it.symbol == symbol) - -proc changeAccountSettings*(self: WalletModel, address: string, accountName: string, color: string): string = - var selectedAccount: WalletAccount - for account in self.accounts: - if (account.address == address): - selectedAccount = account - break - if (isNil(selectedAccount)): - result = "No account found with that address" - error "No account found with that address", address - selectedAccount.name = accountName - selectedAccount.iconColor = color - result = status_accounts.changeAccount(selectedAccount.name, selectedAccount.address, - selectedAccount.publicKey, selectedAccount.walletType, selectedAccount.iconColor) - -proc deleteAccount*(self: WalletModel, address: string): string = - result = status_accounts.deleteAccount(address) - self.accounts = self.accounts.filter(acc => acc.address.toLowerAscii != address.toLowerAscii) - -proc toggleAsset*(self: WalletModel, symbol: string) = - self.tokens = status_tokens.toggleAsset(symbol) - for account in self.accounts: - account.assetList = self.generateAccountConfiguredAssets(account.address) - updateBalance(account, self.getDefaultCurrency()) - self.events.emit("assetChanged", Args()) - -proc hideAsset*(self: WalletModel, symbol: string) = - status_tokens.hideAsset(symbol) - self.tokens = status_tokens.getVisibleTokens() - for account in self.accounts: - account.assetList = self.generateAccountConfiguredAssets(account.address) - updateBalance(account, self.getDefaultCurrency()) - self.events.emit("assetChanged", Args()) - -proc addCustomToken*(self: WalletModel, symbol: string, enable: bool, address: string, name: string, decimals: int, color: string) = - addCustomToken(address, name, symbol, decimals, color) - -proc getTransfersByAddress*(self: WalletModel, address: string, toBlock: Uint256, limit: int, loadMore: bool): seq[Transaction] = - result = status_wallet.getTransfersByAddress(address, toBlock, limit, loadMore) - -proc validateMnemonic*(self: WalletModel, mnemonic: string): string = - result = status_wallet.validateMnemonic(mnemonic).parseJSON()["error"].getStr - -proc getGasPricePredictions*(): GasPricePrediction = - if status_settings.getCurrentNetwork() != Network.Mainnet: - # TODO: what about other chains like xdai? - return GasPricePrediction(safeLow: 1.0, standard: 2.0, fast: 3.0, fastest: 4.0) - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - try: - let url: string = fmt"https://etherchain.org/api/gasPriceOracle" - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - let response = client.request(url) - result = Json.decode(response.body, GasPricePrediction) - except Exception as e: - echo "error getting gas price predictions" - echo e.msg - finally: - client.close() - -proc checkRecentHistory*(self: WalletModel, addresses: seq[string]): string = - result = status_wallet.checkRecentHistory(addresses) - -proc setInitialBlocksRange*(self: WalletModel): string = - result = status_wallet.setInitialBlocksRange() - -proc getWalletAccounts*(self: WalletModel): seq[WalletAccount] = - result = status_wallet.getWalletAccounts() - -proc getWalletAccounts*(): seq[WalletAccount] = - result = status_wallet.getWalletAccounts() - -proc watchTransaction*(self: WalletModel, transactionHash: string): string = - result = status_wallet.watchTransaction(transactionHash) - -proc getPendingTransactions*(self: WalletModel): string = - result = status_wallet.getPendingTransactions() - -# proc getTransfersByAddress*(address: string): seq[types.Transaction] = - # result = status_wallet.getTransfersByAddress(address) - -proc getTransfersByAddress*(address: string, toBlock: Uint256, limit: int, loadMore: bool): seq[Transaction] = - result = status_wallet.getTransfersByAddress(address, toBlock, limit, loadMore) - -proc watchTransaction*(transactionHash: string): string = - result = status_wallet.watchTransaction(transactionHash) - -proc hex2Token*(self: WalletModel, input: string, decimals: int): string = - result = status_wallet.hex2Token(input, decimals) - -proc getOpenseaCollections*(address: string): string = - result = status_wallet.getOpenseaCollections(address) - -proc getOpenseaAssets*(address: string, collectionSlug: string, limit: int): string = - result = status_wallet.getOpenseaAssets(address, collectionSlug, limit) \ No newline at end of file diff --git a/src/status/wallet/account.nim b/src/status/wallet/account.nim deleted file mode 100644 index 543e42d244..0000000000 --- a/src/status/wallet/account.nim +++ /dev/null @@ -1,62 +0,0 @@ -import options, json, strformat - -from ../../eventemitter import Args -import ../types/[transaction] - -type CollectibleList* = ref object - collectibleType*, collectiblesJSON*, error*: string - loading*: int - -type Collectible* = ref object - name*, image*, id*, collectibleType*, description*, externalUrl*: string - -type OpenseaCollection* = ref object - name*, slug*, imageUrl*: string - ownedAssetCount*: int - -type OpenseaAsset* = ref object - id*: int - name*, description*, permalink*, imageThumbnailUrl*, imageUrl*, address*: string - -type CurrencyArgs* = ref object of Args - currency*: string - -type Asset* = ref object - name*, symbol*, value*, fiatBalanceDisplay*, fiatBalance*, accountAddress*, address*: string - -type WalletAccount* = ref object - name*, address*, iconColor*, path*, walletType*, publicKey*: string - balance*: Option[string] - realFiatBalance*: Option[float] - assetList*: seq[Asset] - wallet*, chat*: bool - collectiblesLists*: seq[CollectibleList] - transactions*: tuple[hasMore: bool, data: seq[Transaction]] - -type AccountArgs* = ref object of Args - account*: WalletAccount - -proc `$`*(self: OpenseaCollection): string = - return fmt"OpenseaCollection(name:{self.name}, slug:{self.slug}, owned asset count:{self.ownedAssetCount})" - -proc `$`*(self: OpenseaAsset): string = - return fmt"OpenseaAsset(id:{self.id}, name:{self.name}, address:{self.address}, imageUrl: {self.imageUrl}, imageThumbnailUrl: {self.imageThumbnailUrl})" - -proc toOpenseaCollection*(jsonCollection: JsonNode): OpenseaCollection = - return OpenseaCollection( - name: jsonCollection{"name"}.getStr, - slug: jsonCollection{"slug"}.getStr, - imageUrl: jsonCollection{"image_url"}.getStr, - ownedAssetCount: jsonCollection{"owned_asset_count"}.getInt - ) - -proc toOpenseaAsset*(jsonAsset: JsonNode): OpenseaAsset = - return OpenseaAsset( - id: jsonAsset{"id"}.getInt, - name: jsonAsset{"name"}.getStr, - description: jsonAsset{"description"}.getStr, - permalink: jsonAsset{"permalink"}.getStr, - imageThumbnailUrl: jsonAsset{"image_thumbnail_url"}.getStr, - imageUrl: jsonAsset{"image_url"}.getStr, - address: jsonAsset{"asset_contract"}{"address"}.getStr - ) \ No newline at end of file diff --git a/src/status/wallet/balance_manager.nim b/src/status/wallet/balance_manager.nim deleted file mode 100644 index 13823da08b..0000000000 --- a/src/status/wallet/balance_manager.nim +++ /dev/null @@ -1,90 +0,0 @@ -import strformat, strutils, stint, httpclient, json, chronicles, net -import ../libstatus/wallet as status_wallet -import ../libstatus/tokens as status_tokens -import ../types/[rpc_response] -import ../utils/cache -import account -import options - -logScope: - topics = "balance-manager" - -type BalanceManager* = ref object - pricePairs: CachedValues - tokenBalances: CachedValues - -proc newBalanceManager*(): BalanceManager = - result = BalanceManager() - result.pricePairs = newCachedValues() - result.tokenBalances = newCachedValues() - -var balanceManager = newBalanceManager() - -proc getPrice(crypto: string, fiat: string): string = - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - try: - let url: string = fmt"https://min-api.cryptocompare.com/data/price?fsym={crypto}&tsyms={fiat}" - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - result = $parseJson(response.body)[fiat.toUpper] - except Exception as e: - error "Error getting price", message = e.msg - result = "0.0" - finally: - client.close() - -proc getEthBalance(address: string): string = - var balance = status_wallet.getBalance(address) - result = status_wallet.hex2token(balance, 18) - -proc getBalance*(symbol: string, accountAddress: string, tokenAddress: string, refreshCache: bool): string = - let cacheKey = fmt"{symbol}-{accountAddress}-{tokenAddress}" - if not refreshCache and balanceManager.tokenBalances.isCached(cacheKey): - return balanceManager.tokenBalances.get(cacheKey) - - if symbol == "ETH": - let ethBalance = getEthBalance(accountAddress) - return ethBalance - - result = $status_tokens.getTokenBalance(tokenAddress, accountAddress) - balanceManager.tokenBalances.cacheValue(cacheKey, result) - -proc convertValue*(balance: string, fromCurrency: string, toCurrency: string): float = - if balance == "0.0": return 0.0 - let cacheKey = fmt"{fromCurrency}-{toCurrency}" - if balanceManager.pricePairs.isCached(cacheKey): - return parseFloat(balance) * parseFloat(balanceManager.pricePairs.get(cacheKey)) - - var fiat_crypto_price = getPrice(fromCurrency, toCurrency) - balanceManager.pricePairs.cacheValue(cacheKey, fiat_crypto_price) - parseFloat(balance) * parseFloat(fiat_crypto_price) - -proc updateBalance*(asset: Asset, currency: string, refreshCache: bool): float = - var token_balance = getBalance(asset.symbol, asset.accountAddress, asset.address, refreshCache) - let fiat_balance = convertValue(token_balance, asset.symbol, currency) - asset.value = token_balance - asset.fiatBalanceDisplay = fmt"{fiat_balance:.2f} {currency}" - asset.fiatBalance = fmt"{fiat_balance:.2f}" - return fiat_balance - -proc updateBalance*(account: WalletAccount, currency: string, refreshCache: bool = false) = - try: - var usd_balance = 0.0 - for asset in account.assetList: - let assetFiatBalance = updateBalance(asset, currency, refreshCache) - usd_balance = usd_balance + assetFiatBalance - - account.realFiatBalance = some(usd_balance) - account.balance = some(fmt"{usd_balance:.2f} {currency}") - except RpcException: - error "Error in updateBalance", message = getCurrentExceptionMsg() - -proc storeBalances*(account: WalletAccount, ethBalance = "0", tokenBalance: JsonNode) = - let ethCacheKey = fmt"ETH-{account.address}-" - balanceManager.tokenBalances.cacheValue(ethCacheKey, ethBalance) - for asset in account.assetList: - if tokenBalance.hasKey(asset.address): - let cacheKey = fmt"{asset.symbol}-{account.address}-{asset.address}" - balanceManager.tokenBalances.cacheValue(cacheKey, tokenBalance{asset.address}.getStr()) diff --git a/src/status/wallet/collectibles.nim b/src/status/wallet/collectibles.nim deleted file mode 100644 index 768492d172..0000000000 --- a/src/status/wallet/collectibles.nim +++ /dev/null @@ -1,259 +0,0 @@ -import # std libs - atomics, strformat, httpclient, json, chronicles, sequtils, strutils, tables, - sugar, net - -import # vendor libs - stint - -import # status-desktop libs - ../libstatus/core as status, ../libstatus/eth/contracts as contracts, - ../stickers as status_stickers, - web3/[conversions, ethtypes], ../utils, account - -const CRYPTOKITTY* = "cryptokitty" -const KUDO* = "kudo" -const ETHERMON* = "ethermon" -const STICKER* = "stickers" - -const COLLECTIBLE_TYPES* = [CRYPTOKITTY, KUDO, ETHERMON, STICKER] - -const MAX_TOKENS = 200 - -proc getTokenUri(contract: Erc721Contract, tokenId: Stuint[256]): string = - try: - let - tokenUri = TokenUri(tokenId: tokenId) - payload = %* [{ - "to": $contract.address, - "data": contract.methods["tokenURI"].encodeAbi(tokenUri) - }, "latest"] - response = callPrivateRPC("eth_call", payload) - var postfixedResult: string = parseJson($response)["result"].str - postfixedResult.removeSuffix('0') - postfixedResult.removePrefix("0x") - postfixedResult = parseHexStr(postfixedResult) - let index = postfixedResult.find("http") - if (index < -1): - return "" - result = postfixedResult[index .. postfixedResult.high] - except Exception as e: - error "Error getting the token URI", mes = e.msg - result = "" - -proc tokenOfOwnerByIndex(contract: Erc721Contract, address: Address, index: Stuint[256]): int = - let - tokenOfOwnerByIndex = TokenOfOwnerByIndex(address: address, index: index) - payload = %* [{ - "to": $contract.address, - "data": contract.methods["tokenOfOwnerByIndex"].encodeAbi(tokenOfOwnerByIndex) - }, "latest"] - response = callPrivateRPC("eth_call", payload) - jsonResponse = parseJson($response) - if (not jsonResponse.hasKey("result")): - return -1 - let res = jsonResponse["result"].getStr - if (res == "0x"): - return -1 - result = fromHex[int](res) - -proc balanceOf(contract: Erc721Contract, address: Address): int = - let - balanceOf = BalanceOf(address: address) - payload = %* [{ - "to": $contract.address, - "data": contract.methods["balanceOf"].encodeAbi(balanceOf) - }, "latest"] - response = callPrivateRPC("eth_call", payload) - jsonResponse = parseJson($response) - if (not jsonResponse.hasKey("result")): - return 0 - let res = jsonResponse["result"].getStr - if (res == "0x"): - return 0 - result = fromHex[int](res) - -proc tokensOfOwnerByIndex(contract: Erc721Contract, address: Address): seq[int] = - var index = 0 - var token: int - var maxIndex: int = balanceOf(contract, address) - result = @[] - while index < maxIndex and result.len <= MAX_TOKENS: - token = tokenOfOwnerByIndex(contract, address, index.u256) - result.add(token) - index = index + 1 - - return result - -proc getCryptoKittiesBatch*(address: Address, offset: int = 0): seq[Collectible] = - var cryptokitties: seq[Collectible] - cryptokitties = @[] - # TODO handle testnet -- does this API exist in testnet?? - let url: string = fmt"https://api.cryptokitties.co/kitties?limit=20&offset={$offset}&owner_wallet_address={$address}&parents=false" - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - let responseBody = parseJson(response.body) - let kitties = responseBody["kitties"] - for kitty in kitties: - try: - var id = kitty["id"] - var name = kitty["name"] - var finalId = "" - var finalName = "" - if id.kind != JNull: - finalId = $id - if name.kind != JNull: - finalName = $name - cryptokitties.add(Collectible(id: finalId, - name: finalName, - image: kitty["image_url_png"].str, - collectibleType: CRYPTOKITTY, - description: "", - externalUrl: "")) - except Exception as e2: - error "Error with this individual cat", msg = e2.msg, cat = kitty - - let limit = responseBody["limit"].getInt - let total = responseBody["total"].getInt - let currentCount = limit * (offset + 1) - if (currentCount < total and currentCount < MAX_TOKENS): - # Call the API again with offset + 1 - let nextBatch = getCryptoKittiesBatch(address, offset + 1) - return concat(cryptokitties, nextBatch) - return cryptokitties - -proc getCryptoKitties*(address: Address): string = - try: - let cryptokitties = getCryptoKittiesBatch(address, 0) - - return $(%*cryptokitties) - except Exception as e: - error "Error getting Cryptokitties", msg = e.msg - return e.msg - -proc getCryptoKitties*(address: string): string = - let eth_address = parseAddress(address) - result = getCryptoKitties(eth_address) - -proc getEthermons*(address: Address): string = - try: - var ethermons: seq[Collectible] - ethermons = @[] - let contract = getErc721Contract("ethermon") - if contract == nil: return $(%*ethermons) - - let tokens = tokensOfOwnerByIndex(contract, address) - - if (tokens.len == 0): - return $(%*ethermons) - - let tokensJoined = strutils.join(tokens, ",") - let url = fmt"https://www.ethermon.io/api/monster/get_data?monster_ids={tokensJoined}" - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - let monsters = parseJson(response.body)["data"] - var i = 0 - for monsterKey in json.keys(monsters): - let monster = monsters[monsterKey] - ethermons.add(Collectible(id: $tokens[i], - name: monster["class_name"].str, - image: monster["image"].str, - collectibleType: ETHERMON, - description: "", - externalUrl: "")) - i = i + 1 - - return $(%*ethermons) - except Exception as e: - error "Error getting Ethermons", msg = e.msg - result = e.msg - -proc getEthermons*(address: string): string = - let eth_address = parseAddress(address) - result = getEthermons(eth_address) - -proc getKudos*(address: Address): string = - try: - var kudos: seq[Collectible] - kudos = @[] - let contract = getErc721Contract("kudos") - if contract == nil: return $(%*kudos) - - let tokens = tokensOfOwnerByIndex(contract, address) - - if (tokens.len == 0): - return $(%*kudos) - - for token in tokens: - let url = getTokenUri(contract, token.u256) - - if (url == ""): - return $(%*kudos) - - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - let kudo = parseJson(response.body) - - kudos.add(Collectible(id: $token, - name: kudo["name"].str, - image: kudo["image"].str, - collectibleType: KUDO, - description: kudo["description"].str, - externalUrl: kudo["external_url"].str)) - - return $(%*kudos) - except Exception as e: - error "Error getting Kudos", msg = e.msg - result = e.msg - -proc getKudos*(address: string): string = - let eth_address = parseAddress(address) - result = getKudos(eth_address) - -proc getStickers*(address: Address, running: var Atomic[bool]): string = - try: - var stickers: seq[Collectible] - stickers = @[] - let contract = getErc721Contract("sticker-pack") - if contract == nil: return - - let tokensIds = tokensOfOwnerByIndex(contract, address) - - if (tokensIds.len == 0): - return $(%*stickers) - - let purchasedStickerPacks = tokensIds.map(tokenId => status_stickers.getPackIdFromTokenId(tokenId.u256)) - - if (purchasedStickerPacks.len == 0): - return $(%*stickers) - # TODO find a way to keep those in memory so as not to reload it each time - let availableStickerPacks = getAvailableStickerPacks(running) - - var index = 0 - for stickerId in purchasedStickerPacks: - let sticker = availableStickerPacks[stickerId] - stickers.add(Collectible(id: $tokensIds[index], - name: sticker.name, - image: fmt"https://ipfs.infura.io/ipfs/{status_stickers.decodeContentHash(sticker.preview)}", - collectibleType: STICKER, - description: sticker.author, - externalUrl: "") - ) - index = index + 1 - - return $(%*stickers) - except Exception as e: - error "Error getting Stickers", msg = e.msg - result = e.msg - -proc getStickers*(address: string, running: var Atomic[bool]): string = - let eth_address = parseAddress(address) - result = getStickers(eth_address, running) diff --git a/src/status/wallet2.nim b/src/status/wallet2.nim deleted file mode 100644 index 51590adef8..0000000000 --- a/src/status/wallet2.nim +++ /dev/null @@ -1,213 +0,0 @@ -import json, strformat, options, chronicles, sugar, sequtils, strutils - -import libstatus/accounts as status_accounts -import libstatus/accounts/constants as constants -import libstatus/tokens as status_tokens -import libstatus/wallet as status_wallet -import libstatus/settings as status_settings -import libstatus/eth/[contracts] -import wallet2/[balance_manager, collectibles] -import wallet2/account as wallet_account -import ./types/[account, transaction, network, setting, gas_prediction, rpc_response] -import ../eventemitter -from web3/ethtypes import Address -from web3/conversions import `$` - -export wallet_account, collectibles - -logScope: - topics = "status-wallet2" - -type - CryptoServicesArg* = ref object of Args - services*: JsonNode # an array - -type - StatusWalletController* = ref object - events: EventEmitter - accounts: seq[WalletAccount] - tokens: seq[Erc20Contract] - totalBalance*: float - -# Forward declarations -proc initEvents*(self: StatusWalletController) -proc generateAccountConfiguredAssets*(self: StatusWalletController, - accountAddress: string): seq[Asset] -proc calculateTotalFiatBalance*(self: StatusWalletController) - -proc setup(self: StatusWalletController, events: EventEmitter) = - self.events = events - self.accounts = @[] - self.tokens = @[] - self.totalBalance = 0.0 - self.initEvents() - -proc delete*(self: StatusWalletController) = - discard - -proc newStatusWalletController*(events: EventEmitter): - StatusWalletController = - result = StatusWalletController() - result.setup(events) - -proc initTokens(self: StatusWalletController) = - self.tokens = status_tokens.getVisibleTokens() - -proc initAccounts(self: StatusWalletController) = - let accounts = status_wallet.getWalletAccounts() - for acc in accounts: - var assets: seq[Asset] = self.generateAccountConfiguredAssets(acc.address) - var walletAccount = newWalletAccount(acc.name, acc.address, acc.iconColor, - acc.path, acc.walletType, acc.publicKey, acc.wallet, acc.chat, assets) - self.accounts.add(walletAccount) - -proc init*(self: StatusWalletController) = - self.initTokens() - self.initAccounts() - -proc initEvents*(self: StatusWalletController) = - self.events.on("currencyChanged") do(e: Args): - self.events.emit("accountsUpdated", Args()) - - self.events.on("newAccountAdded") do(e: Args): - self.calculateTotalFiatBalance() - -proc getAccounts*(self: StatusWalletController): seq[WalletAccount] = - self.accounts - -proc getDefaultCurrency*(self: StatusWalletController): string = -# TODO: this should come from a model? It is going to be used too in the -# profile section and ideally we should not call the settings more than once - status_settings.getSetting[string](Setting.Currency, "usd") - -proc generateAccountConfiguredAssets*(self: StatusWalletController, - accountAddress: string): seq[Asset] = - var assets: seq[Asset] = @[] - var asset = Asset(name:"Ethereum", symbol: "ETH", value: "0.0", - fiatBalanceDisplay: "0.0", accountAddress: accountAddress) - assets.add(asset) - for token in self.tokens: - var symbol = token.symbol - var existingToken = Asset(name: token.name, symbol: symbol, - value: fmt"0.0", fiatBalanceDisplay: "$0.0", accountAddress: accountAddress, - address: $token.address) - assets.add(existingToken) - assets - -proc calculateTotalFiatBalance*(self: StatusWalletController) = - self.totalBalance = 0.0 - for account in self.accounts: - if account.realFiatBalance.isSome: - self.totalBalance += account.realFiatBalance.get() - -proc newAccount*(self: StatusWalletController, walletType: string, derivationPath: string, - name: string, address: string, iconColor: string, balance: string, - publicKey: string): WalletAccount = - var assets: seq[Asset] = self.generateAccountConfiguredAssets(address) - var account = WalletAccount(name: name, path: derivationPath, walletType: walletType, - address: address, iconColor: iconColor, balance: none[string](), assetList: assets, - realFiatBalance: none[float](), publicKey: publicKey) - updateBalance(account, self.getDefaultCurrency()) - account - -proc addNewGeneratedAccount(self: StatusWalletController, generatedAccount: GeneratedAccount, - password: string, accountName: string, color: string, accountType: string, - isADerivedAccount = true, walletIndex: int = 0) = - try: - generatedAccount.name = accountName - var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, - password, color, accountType, isADerivedAccount, walletIndex) - var account = self.newAccount(accountType, derivedAccount.derivationPath, - accountName, derivedAccount.address, color, fmt"0.00 {self.getDefaultCurrency()}", - derivedAccount.publicKey) - - self.accounts.add(account) - # wallet_checkRecentHistory is required to be called when a new account is - # added before wallet_getTransfersByAddress can be called. This is because - # wallet_checkRecentHistory populates the status-go db that - # wallet_getTransfersByAddress reads from - discard status_wallet.checkRecentHistory(self.accounts.map(account => account.address)) - self.events.emit("newAccountAdded", wallet_account.AccountArgs(account: account)) - except Exception as e: - raise newException(StatusGoException, fmt"Error adding new account: {e.msg}") - -proc generateNewAccount*(self: StatusWalletController, password: string, accountName: string, color: string) = - let - walletRootAddress = status_settings.getSetting[string](Setting.WalletRootAddress, "") - walletIndex = status_settings.getSetting[int](Setting.LatestDerivedPath) + 1 - loadedAccount = status_accounts.loadAccount(walletRootAddress, password) - derivedAccount = status_accounts.deriveWallet(loadedAccount.id, walletIndex) - generatedAccount = GeneratedAccount( - id: loadedAccount.id, - publicKey: derivedAccount.publicKey, - address: derivedAccount.address - ) - - # if we've gotten here, the password is ok (loadAccount requires a valid password) - # so no need to check for a valid password - self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.GENERATED, true, walletIndex) - - let statusGoResult = status_settings.saveSetting(Setting.LatestDerivedPath, $walletIndex) - if statusGoResult.error != "": - error "Error storing the latest wallet index", msg=statusGoResult.error - -proc addAccountsFromSeed*(self: StatusWalletController, seed: string, password: string, accountName: string, color: string) = - let mnemonic = replace(seed, ',', ' ') - var generatedAccount = status_accounts.multiAccountImportMnemonic(mnemonic) - generatedAccount.derived = status_accounts.deriveAccounts(generatedAccount.id) - - let - defaultAccount = status_accounts.getDefaultAccount() - isPasswordOk = status_accounts.verifyAccountPassword(defaultAccount, password) - if not isPasswordOk: - raise newException(StatusGoException, "Error generating new account: invalid password") - - self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.SEED) - -proc addAccountsFromPrivateKey*(self: StatusWalletController, privateKey: string, password: string, accountName: string, color: string) = - let - generatedAccount = status_accounts.MultiAccountImportPrivateKey(privateKey) - defaultAccount = status_accounts.getDefaultAccount() - isPasswordOk = status_accounts.verifyAccountPassword(defaultAccount, password) - - if not isPasswordOk: - raise newException(StatusGoException, "Error generating new account: invalid password") - - self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.KEY, false) - -proc addWatchOnlyAccount*(self: StatusWalletController, address: string, accountName: string, color: string) = - let account = GeneratedAccount(address: address) - self.addNewGeneratedAccount(account, "", accountName, color, constants.WATCH, false) - -proc changeAccountSettings*(self: StatusWalletController, address: string, accountName: string, color: string): string = - var selectedAccount: WalletAccount - for account in self.accounts: - if (account.address == address): - selectedAccount = account - break - if (isNil(selectedAccount)): - result = "No account found with that address" - error "No account found with that address", address - selectedAccount.name = accountName - selectedAccount.iconColor = color - result = status_accounts.changeAccount(selectedAccount.name, selectedAccount.address, - selectedAccount.publicKey, selectedAccount.walletType, selectedAccount.iconColor) - -proc deleteAccount*(self: StatusWalletController, address: string): string = - result = status_accounts.deleteAccount(address) - self.accounts = self.accounts.filter(acc => acc.address.toLowerAscii != address.toLowerAscii) - -proc getOpenseaCollections*(address: string): string = - result = status_wallet.getOpenseaCollections(address) - -proc getOpenseaAssets*(address: string, collectionSlug: string, limit: int): string = - result = status_wallet.getOpenseaAssets(address, collectionSlug, limit) - -proc onAsyncFetchCryptoServices*(self: StatusWalletController, response: string) = - let responseArray = response.parseJson - if (responseArray.kind != JArray): - info "received crypto services is not a json array" - self.events.emit("cryptoServicesFetched", CryptoServicesArg()) - return - - self.events.emit("cryptoServicesFetched", CryptoServicesArg(services: responseArray)) \ No newline at end of file diff --git a/src/status/wallet2/account.nim b/src/status/wallet2/account.nim deleted file mode 100644 index deeb86bef8..0000000000 --- a/src/status/wallet2/account.nim +++ /dev/null @@ -1,77 +0,0 @@ -import options, json, strformat - -from ../../eventemitter import Args -import ../types/[transaction] - -type CollectibleList* = ref object - collectibleType*, collectiblesJSON*, error*: string - loading*: int - -type Collectible* = ref object - name*, image*, id*, collectibleType*, description*, externalUrl*: string - -type OpenseaCollection* = ref object - name*, slug*, imageUrl*: string - ownedAssetCount*: int - -type OpenseaAsset* = ref object - id*: int - name*, description*, permalink*, imageThumbnailUrl*, imageUrl*, address*: string - -type CurrencyArgs* = ref object of Args - currency*: string - -type Asset* = ref object - name*, symbol*, value*, fiatBalanceDisplay*, fiatBalance*, accountAddress*, address*: string - -type WalletAccount* = ref object - name*, address*, iconColor*, path*, walletType*, publicKey*: string - balance*: Option[string] - realFiatBalance*: Option[float] - assetList*: seq[Asset] - wallet*, chat*: bool - collectiblesLists*: seq[CollectibleList] - transactions*: tuple[hasMore: bool, data: seq[Transaction]] - -proc newWalletAccount*(name, address, iconColor, path, walletType, publicKey: string, - wallet, chat: bool, assets: seq[Asset]): WalletAccount = - result = new WalletAccount - result.name = name - result.address = address - result.iconColor = iconColor - result.path = path - result.walletType = walletType - result.publicKey = publicKey - result.wallet = wallet - result.chat = chat - result.assetList = assets - result.balance = none[string]() - result.realFiatBalance = none[float]() - -type AccountArgs* = ref object of Args - account*: WalletAccount - -proc `$`*(self: OpenseaCollection): string = - return fmt"OpenseaCollection(name:{self.name}, slug:{self.slug}, owned asset count:{self.ownedAssetCount})" - -proc `$`*(self: OpenseaAsset): string = - return fmt"OpenseaAsset(id:{self.id}, name:{self.name}, address:{self.address}, imageUrl: {self.imageUrl}, imageThumbnailUrl: {self.imageThumbnailUrl})" - -proc toOpenseaCollection*(jsonCollection: JsonNode): OpenseaCollection = - return OpenseaCollection( - name: jsonCollection{"name"}.getStr, - slug: jsonCollection{"slug"}.getStr, - imageUrl: jsonCollection{"image_url"}.getStr, - ownedAssetCount: jsonCollection{"owned_asset_count"}.getInt - ) - -proc toOpenseaAsset*(jsonAsset: JsonNode): OpenseaAsset = - return OpenseaAsset( - id: jsonAsset{"id"}.getInt, - name: jsonAsset{"name"}.getStr, - description: jsonAsset{"description"}.getStr, - permalink: jsonAsset{"permalink"}.getStr, - imageThumbnailUrl: jsonAsset{"image_thumbnail_url"}.getStr, - imageUrl: jsonAsset{"image_url"}.getStr, - address: jsonAsset{"asset_contract"}{"address"}.getStr - ) \ No newline at end of file diff --git a/src/status/wallet2/balance_manager.nim b/src/status/wallet2/balance_manager.nim deleted file mode 100644 index d51b91fc7d..0000000000 --- a/src/status/wallet2/balance_manager.nim +++ /dev/null @@ -1,90 +0,0 @@ -import strformat, strutils, stint, httpclient, json, chronicles, net -import ../libstatus/wallet as status_wallet -import ../libstatus/tokens as status_tokens -import ../types/[rpc_response] -import ../utils/cache -import account -import options - -logScope: - topics = "status-wallet2-balance-manager" - -type BalanceManager* = ref object - pricePairs: CachedValues - tokenBalances: CachedValues - -proc newBalanceManager*(): BalanceManager = - result = BalanceManager() - result.pricePairs = newCachedValues() - result.tokenBalances = newCachedValues() - -var balanceManager = newBalanceManager() - -proc getPrice(crypto: string, fiat: string): string = - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - try: - let url: string = fmt"https://min-api.cryptocompare.com/data/price?fsym={crypto}&tsyms={fiat}" - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - result = $parseJson(response.body)[fiat.toUpper] - except Exception as e: - error "Error getting price", message = e.msg - result = "0.0" - finally: - client.close() - -proc getEthBalance(address: string): string = - var balance = status_wallet.getBalance(address) - result = status_wallet.hex2token(balance, 18) - -proc getBalance*(symbol: string, accountAddress: string, tokenAddress: string, refreshCache: bool): string = - let cacheKey = fmt"{symbol}-{accountAddress}-{tokenAddress}" - if not refreshCache and balanceManager.tokenBalances.isCached(cacheKey): - return balanceManager.tokenBalances.get(cacheKey) - - if symbol == "ETH": - let ethBalance = getEthBalance(accountAddress) - return ethBalance - - result = $status_tokens.getTokenBalance(tokenAddress, accountAddress) - balanceManager.tokenBalances.cacheValue(cacheKey, result) - -proc convertValue*(balance: string, fromCurrency: string, toCurrency: string): float = - if balance == "0.0": return 0.0 - let cacheKey = fmt"{fromCurrency}-{toCurrency}" - if balanceManager.pricePairs.isCached(cacheKey): - return parseFloat(balance) * parseFloat(balanceManager.pricePairs.get(cacheKey)) - - var fiat_crypto_price = getPrice(fromCurrency, toCurrency) - balanceManager.pricePairs.cacheValue(cacheKey, fiat_crypto_price) - parseFloat(balance) * parseFloat(fiat_crypto_price) - -proc updateBalance*(asset: Asset, currency: string, refreshCache: bool): float = - var token_balance = getBalance(asset.symbol, asset.accountAddress, asset.address, refreshCache) - let fiat_balance = convertValue(token_balance, asset.symbol, currency) - asset.value = token_balance - asset.fiatBalanceDisplay = fmt"{fiat_balance:.2f} {currency}" - asset.fiatBalance = fmt"{fiat_balance:.2f}" - return fiat_balance - -proc updateBalance*(account: WalletAccount, currency: string, refreshCache: bool = false) = - try: - var usd_balance = 0.0 - for asset in account.assetList: - let assetFiatBalance = updateBalance(asset, currency, refreshCache) - usd_balance = usd_balance + assetFiatBalance - - account.realFiatBalance = some(usd_balance) - account.balance = some(fmt"{usd_balance:.2f} {currency}") - except RpcException: - error "Error in updateBalance", message = getCurrentExceptionMsg() - -proc storeBalances*(account: WalletAccount, ethBalance = "0", tokenBalance: JsonNode) = - let ethCacheKey = fmt"ETH-{account.address}-" - balanceManager.tokenBalances.cacheValue(ethCacheKey, ethBalance) - for asset in account.assetList: - if tokenBalance.hasKey(asset.address): - let cacheKey = fmt"{asset.symbol}-{account.address}-{asset.address}" - balanceManager.tokenBalances.cacheValue(cacheKey, tokenBalance{asset.address}.getStr()) diff --git a/src/status/wallet2/collectibles.nim b/src/status/wallet2/collectibles.nim deleted file mode 100644 index 768492d172..0000000000 --- a/src/status/wallet2/collectibles.nim +++ /dev/null @@ -1,259 +0,0 @@ -import # std libs - atomics, strformat, httpclient, json, chronicles, sequtils, strutils, tables, - sugar, net - -import # vendor libs - stint - -import # status-desktop libs - ../libstatus/core as status, ../libstatus/eth/contracts as contracts, - ../stickers as status_stickers, - web3/[conversions, ethtypes], ../utils, account - -const CRYPTOKITTY* = "cryptokitty" -const KUDO* = "kudo" -const ETHERMON* = "ethermon" -const STICKER* = "stickers" - -const COLLECTIBLE_TYPES* = [CRYPTOKITTY, KUDO, ETHERMON, STICKER] - -const MAX_TOKENS = 200 - -proc getTokenUri(contract: Erc721Contract, tokenId: Stuint[256]): string = - try: - let - tokenUri = TokenUri(tokenId: tokenId) - payload = %* [{ - "to": $contract.address, - "data": contract.methods["tokenURI"].encodeAbi(tokenUri) - }, "latest"] - response = callPrivateRPC("eth_call", payload) - var postfixedResult: string = parseJson($response)["result"].str - postfixedResult.removeSuffix('0') - postfixedResult.removePrefix("0x") - postfixedResult = parseHexStr(postfixedResult) - let index = postfixedResult.find("http") - if (index < -1): - return "" - result = postfixedResult[index .. postfixedResult.high] - except Exception as e: - error "Error getting the token URI", mes = e.msg - result = "" - -proc tokenOfOwnerByIndex(contract: Erc721Contract, address: Address, index: Stuint[256]): int = - let - tokenOfOwnerByIndex = TokenOfOwnerByIndex(address: address, index: index) - payload = %* [{ - "to": $contract.address, - "data": contract.methods["tokenOfOwnerByIndex"].encodeAbi(tokenOfOwnerByIndex) - }, "latest"] - response = callPrivateRPC("eth_call", payload) - jsonResponse = parseJson($response) - if (not jsonResponse.hasKey("result")): - return -1 - let res = jsonResponse["result"].getStr - if (res == "0x"): - return -1 - result = fromHex[int](res) - -proc balanceOf(contract: Erc721Contract, address: Address): int = - let - balanceOf = BalanceOf(address: address) - payload = %* [{ - "to": $contract.address, - "data": contract.methods["balanceOf"].encodeAbi(balanceOf) - }, "latest"] - response = callPrivateRPC("eth_call", payload) - jsonResponse = parseJson($response) - if (not jsonResponse.hasKey("result")): - return 0 - let res = jsonResponse["result"].getStr - if (res == "0x"): - return 0 - result = fromHex[int](res) - -proc tokensOfOwnerByIndex(contract: Erc721Contract, address: Address): seq[int] = - var index = 0 - var token: int - var maxIndex: int = balanceOf(contract, address) - result = @[] - while index < maxIndex and result.len <= MAX_TOKENS: - token = tokenOfOwnerByIndex(contract, address, index.u256) - result.add(token) - index = index + 1 - - return result - -proc getCryptoKittiesBatch*(address: Address, offset: int = 0): seq[Collectible] = - var cryptokitties: seq[Collectible] - cryptokitties = @[] - # TODO handle testnet -- does this API exist in testnet?? - let url: string = fmt"https://api.cryptokitties.co/kitties?limit=20&offset={$offset}&owner_wallet_address={$address}&parents=false" - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - let responseBody = parseJson(response.body) - let kitties = responseBody["kitties"] - for kitty in kitties: - try: - var id = kitty["id"] - var name = kitty["name"] - var finalId = "" - var finalName = "" - if id.kind != JNull: - finalId = $id - if name.kind != JNull: - finalName = $name - cryptokitties.add(Collectible(id: finalId, - name: finalName, - image: kitty["image_url_png"].str, - collectibleType: CRYPTOKITTY, - description: "", - externalUrl: "")) - except Exception as e2: - error "Error with this individual cat", msg = e2.msg, cat = kitty - - let limit = responseBody["limit"].getInt - let total = responseBody["total"].getInt - let currentCount = limit * (offset + 1) - if (currentCount < total and currentCount < MAX_TOKENS): - # Call the API again with offset + 1 - let nextBatch = getCryptoKittiesBatch(address, offset + 1) - return concat(cryptokitties, nextBatch) - return cryptokitties - -proc getCryptoKitties*(address: Address): string = - try: - let cryptokitties = getCryptoKittiesBatch(address, 0) - - return $(%*cryptokitties) - except Exception as e: - error "Error getting Cryptokitties", msg = e.msg - return e.msg - -proc getCryptoKitties*(address: string): string = - let eth_address = parseAddress(address) - result = getCryptoKitties(eth_address) - -proc getEthermons*(address: Address): string = - try: - var ethermons: seq[Collectible] - ethermons = @[] - let contract = getErc721Contract("ethermon") - if contract == nil: return $(%*ethermons) - - let tokens = tokensOfOwnerByIndex(contract, address) - - if (tokens.len == 0): - return $(%*ethermons) - - let tokensJoined = strutils.join(tokens, ",") - let url = fmt"https://www.ethermon.io/api/monster/get_data?monster_ids={tokensJoined}" - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - let monsters = parseJson(response.body)["data"] - var i = 0 - for monsterKey in json.keys(monsters): - let monster = monsters[monsterKey] - ethermons.add(Collectible(id: $tokens[i], - name: monster["class_name"].str, - image: monster["image"].str, - collectibleType: ETHERMON, - description: "", - externalUrl: "")) - i = i + 1 - - return $(%*ethermons) - except Exception as e: - error "Error getting Ethermons", msg = e.msg - result = e.msg - -proc getEthermons*(address: string): string = - let eth_address = parseAddress(address) - result = getEthermons(eth_address) - -proc getKudos*(address: Address): string = - try: - var kudos: seq[Collectible] - kudos = @[] - let contract = getErc721Contract("kudos") - if contract == nil: return $(%*kudos) - - let tokens = tokensOfOwnerByIndex(contract, address) - - if (tokens.len == 0): - return $(%*kudos) - - for token in tokens: - let url = getTokenUri(contract, token.u256) - - if (url == ""): - return $(%*kudos) - - let secureSSLContext = newContext() - let client = newHttpClient(sslContext = secureSSLContext) - client.headers = newHttpHeaders({ "Content-Type": "application/json" }) - - let response = client.request(url) - let kudo = parseJson(response.body) - - kudos.add(Collectible(id: $token, - name: kudo["name"].str, - image: kudo["image"].str, - collectibleType: KUDO, - description: kudo["description"].str, - externalUrl: kudo["external_url"].str)) - - return $(%*kudos) - except Exception as e: - error "Error getting Kudos", msg = e.msg - result = e.msg - -proc getKudos*(address: string): string = - let eth_address = parseAddress(address) - result = getKudos(eth_address) - -proc getStickers*(address: Address, running: var Atomic[bool]): string = - try: - var stickers: seq[Collectible] - stickers = @[] - let contract = getErc721Contract("sticker-pack") - if contract == nil: return - - let tokensIds = tokensOfOwnerByIndex(contract, address) - - if (tokensIds.len == 0): - return $(%*stickers) - - let purchasedStickerPacks = tokensIds.map(tokenId => status_stickers.getPackIdFromTokenId(tokenId.u256)) - - if (purchasedStickerPacks.len == 0): - return $(%*stickers) - # TODO find a way to keep those in memory so as not to reload it each time - let availableStickerPacks = getAvailableStickerPacks(running) - - var index = 0 - for stickerId in purchasedStickerPacks: - let sticker = availableStickerPacks[stickerId] - stickers.add(Collectible(id: $tokensIds[index], - name: sticker.name, - image: fmt"https://ipfs.infura.io/ipfs/{status_stickers.decodeContentHash(sticker.preview)}", - collectibleType: STICKER, - description: sticker.author, - externalUrl: "") - ) - index = index + 1 - - return $(%*stickers) - except Exception as e: - error "Error getting Stickers", msg = e.msg - result = e.msg - -proc getStickers*(address: string, running: var Atomic[bool]): string = - let eth_address = parseAddress(address) - result = getStickers(eth_address, running) diff --git a/vendor/nim-status-lib b/vendor/nim-status-lib new file mode 160000 index 0000000000..0b24d7a341 --- /dev/null +++ b/vendor/nim-status-lib @@ -0,0 +1 @@ +Subproject commit 0b24d7a341dadcfdf59c6dbbb93506b6bb20bf66