· 7 years ago · Feb 28, 2018, 11:46 AM
1# Simplewallet
2Simplewallet is most users portal to the TurtleCoin network. It is essentially a dumb pipe, which requests data from the RPC interface, TurtleCoind.exe, and then displays this data to the user when required.
3
4Simplewallet unfortunately, along with a lot of the rest of the codebase, makes heavy use of global variables. They are fortunately only global to the .cpp/.h file, but it does make the code a lot harder to follow.
5
6The two most important ones are `m_wallet`, and `m_node`.
7
8### m_wallet
9
10`m_wallet` is the wallet itself, and is an implementation of the IWalletLegacy inteface, this implementation can be found in `src/WalletLegacy/WalletLegacy.cpp`
11Some useful functions this class provide include:
12
13* initAndGenerate - Makes a new wallet file with a password
14* initWithKeys - Restores a wallet with a set of private keys and a password
15* initAndLoad - Loads a wallet from a file with a stream to the file and a password
16* getAccountKeys - Get the wallet public/private spend and view key
17* save - Saves the wallet information back to the wallet file
18* reset - Rewalks the blockchain looking for transactions belonging to the user - can optionally take a parameter to start walking from
19* actualBalance and pendingBalance - pending balance is caused by transactions which haven't been confirmed yet, only included in a block. After a few subsequent blocks these will be moved into actual balance.
20* sendTransaction
21
22### m_node
23
24`m_node` is your connection to the RPC interface, and lets you get more information than just the wallet can provide, such as block info, transaction info, and more. The relevant code can be found in `src/NodeRpcProxy/NodeRpcProxy.cpp`
25
26Some useful functions this class provide include:
27
28* getTransactions - Give it a vector of transaction hashes and it will give you all the information on them, you can then decode this with a users's private keys to determine which outputs belong to them
29* getBlocks - The same as getTransactions, but with a block hash. Each block contains a vector of transactions.
30
31Some of the functions in this class require a callback function - `const Callback& callback`. This is a bit intimidating if you don't know what it means. `Callback` is a typedef for `std::function<void(std::error_code)>;` - That's a function which returns void, and takes an error code as an argument.
32
33When we call one of the functions which require a callback, upon the function completing, it will call this callback function if there was an error. So how the heck do we use it? Here's an example.
34
35```
36/* Here we set up the std::function and the magical async thread things.
37 You can just copy these the next four lines into your program. */
38std::promise<std::error_code> errorPromise;
39std::future<std::error_code> f_error = errorPromise.get_future();
40auto callback = [&errorPromise](std::error_code e) {errorPromise.set_value(e); };
41m_node->addObserver(static_cast<INodeRpcProxyObserver*>(this));
42
43/* Here we call the function we want to use. This function gets us some
44 transaction details for each of the transaction hashes we give it.
45 We pass in the callback as an argument to the function. */
46m_node->getTransactions(transactionHashes, transactions, callback);
47
48/* Now, we check if the function returned an error */
49auto error = f_error.get();
50
51/* If there was an error, we can use the logger object to print it out nicely.
52 More on this later. */
53if (error)
54{
55 logger(ERROR, BRIGHT_RED) << "Failed to find transaction hash! Ensure you entered it correctly and your daemon is fully synced.";
56 return false;
57}
58```
59
60Whilst it is a bit finnicky, the only bit in this example you should need to change is the function you call, and of course what you do when an error occurs.
61
62### Logger
63
64So what's that logger object? It's just a nice way to print messages to the user with pretty colours and timestamps. You can see the colours and the different levels in `/src/Logging/ILogger.cpp`, some nice ones are GREEN, BRIGHT_YELLOW, BRIGHT_RED, AND BRIGHT_WHITE, but there's around 15 to pick from if you're feeling artistic...
65
66The different logger levels allow log messages to be filtered depending upon how high the log level is. A message with FATAL priority will appear even when logging is turned down quite low. You can instrument your code with logger messages in TRACE or DEBUG mode to allow you to easily view what's going on, without spamming users's terminals with tons of messages.
67
68It's very simple to use the logger object, we can just write to it the same way we would `std::cout`. For example:
69
70```
71} catch (const std::exception& e) {
72 logger(ERROR, BRIGHT_RED) << "Failed to store wallet: " << e.what();
73 return 1;
74}
75```
76
77As you can see, we can send both string constants and string variables to it. We don't need to add a `std::endl` to the end, as each separate logger invocation is printed on a newline.
78
79It'll look something like this when it actually gets printed out with all the formatting.
80
81
82
83### refresh_progress_reporter_t
84
85Simplewallet has a class inside of it, refresh_progress_reporter_t. This can be useful to hide implementation details if the classes are tighly coupled, so users don't start using the API and prevent it from being changed. Not sure if we're going to document this or not?
86
87## Public Functions
88
89### simple_wallet(System::Dispatcher &dispatcher, const CryptoNote::Currency ¤cy, Logging::LoggerManager &log) - Constructor
90
91Enter description here...
92
93### bool init(const boost::program_options::variables_map &vm)
94
95### bool deinit()
96
97### bool run()
98
99### void stop()
100
101### bool process_command(const std::vector<std::string> &args)
102
103### std::string get_commands_str()
104
105### const CryptoNote::Currency & currency() const
106
107## Private Functions
108
109### Logging::LoggerMessage success_msg_writer(bool color = false)
110
111### Logging::LoggerMessage fail_msg_writer() const
112
113### void handle_command_line(const boost::program_options::variables_map& vm);
114
115### bool run_console_handler();
116
117### bool new_wallet(const std::string &wallet_file, const std::string& password);
118
119### bool new_wallet(Crypto::SecretKey &secret_key, Crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password);
120
121### bool open_wallet(const std::string &wallet_file, const std::string& password);
122
123### bool close_wallet();
124
125### bool help(const std::vector<std::string> &args = std::vector<std::string>());
126
127### bool exit(const std::vector<std::string> &args);
128
129### bool start_mining(const std::vector<std::string> &args);
130
131### bool stop_mining(const std::vector<std::string> &args);
132
133### bool show_balance(const std::vector<std::string> &args = std::vector<std::string>());
134
135### bool export_keys(const std::vector<std::string> &args = std::vector<std::string>());
136
137### bool show_incoming_transfers(const std::vector<std::string> &args);
138
139### bool show_payments(const std::vector<std::string> &args);
140
141### bool show_blockchain_height(const std::vector<std::string> &args);
142
143### bool listTransfers(const std::vector<std::string> &args);
144
145### bool transfer(const std::vector<std::string> &args);
146
147### bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
148
149### bool print_outputs_from_transaction(const std::vector<std::string> &args);
150
151### bool save(const std::vector<std::string> &args);
152
153### bool reset(const std::vector<std::string> &args);
154
155### bool set_log(const std::vector<std::string> &args);
156
157### bool ask_wallet_create_if_needed();
158
159### std::string generate_mnemonic(Crypto::SecretKey &);
160
161### void log_incorrect_words(std::vector<std::string>);
162
163### bool is_valid_mnemonic(std::string &, Crypto::SecretKey &);
164
165### void printConnectionError() const;
166
167### virtual void initCompleted(std::error_code result) override;
168
169### virtual void externalTransactionCreated(CryptoNote::TransactionId transactionId) override;
170
171### virtual void synchronizationCompleted(std::error_code result) override;
172
173### virtual void synchronizationProgressUpdated(uint32_t current, uint32_t total) override;
174
175### virtual void connectionStatusUpdated(bool connected) override;
176
177## Private Variables
178
179As previously mentioned simplewallet makes heavy use of global header variables.
180
181* std::string m_wallet_file_arg;
182* std::string m_generate_new;
183* std::string m_import_new;
184* std::string m_import_path;
185* std::string m_daemon_address;
186* std::string m_daemon_host;
187* uint16_t m_daemon_port;
188* std::string m_wallet_file;
189* std::string m_restore_view;
190* std::string m_restore_spend;
191* bool sync_from_zero;
192* bool exit_after_generate;
193* uint64_t sync_from_height;
194* std::unique_ptr<std::promise<std::error_code>> m_initResultPromise;
195* Common::ConsoleHandler m_consoleHandler;
196* const CryptoNote::Currency& m_currency;
197* Logging::LoggerManager& logManager;
198* System::Dispatcher& m_dispatcher;
199* Logging::LoggerRef logger;
200* std::unique_ptr<CryptoNote::NodeRpcProxy> m_node;
201* std::unique_ptr<CryptoNote::IWalletLegacy> m_wallet;
202* refresh_progress_reporter_t m_refresh_progress_reporter;
203* bool m_walletSynchronized;
204* std::mutex m_walletSynchronizedMutex;
205* std::condition_variable m_walletSynchronizedCV;