Kevin Gorham
08f95d505d
General fixes and improvements.
2020-01-15 07:35:06 -05:00
Kevin Gorham
3ad1a056a6
Add batch scanning to allow for tracking scan progress.
2020-01-15 07:35:06 -05:00
Kevin Gorham
328e90d241
Add processorInfo for more visibility into status.
2020-01-15 07:35:05 -05:00
Kevin Gorham
e56c1ff24a
Minor refactors and improvements and test fixes.
2020-01-15 07:35:05 -05:00
Kevin Gorham
aaa823081b
Exposed support for address validation.
2020-01-15 07:35:05 -05:00
Kevin Gorham
cf0d86a3da
Remove the bandaid hack that triggered the need for https://github.com/zcash/zcash-android-wallet/issues/39
...
This was a key win in the refactor.
2020-01-15 07:35:04 -05:00
Kevin Gorham
29717cd871
Refactored initialization.
...
Addresses some of the concerns in https://github.com/zcash/zcash-android-wallet/issues/39 by removing the side effects from the Intializer. Now instead of trying to help with loading and persisting wallet birthdates, it delegates that utility to another class.
2020-01-15 07:35:04 -05:00
Kevin Gorham
93c01a9f3f
Test cleanup, deleting outdated tests.
2020-01-15 07:35:04 -05:00
Kevin Gorham
527eb50439
Minor changes to support zECC app.
2020-01-15 07:35:03 -05:00
Kevin Gorham
4653f98053
Added more mainnet sapling trees.
2020-01-15 07:35:03 -05:00
Kevin Gorham
18a4cdfcaa
Added function for abbreviating addresses for user display.
2020-01-15 07:35:03 -05:00
Kevin Gorham
7babe0c63c
Fixed bug with hasData not being cleared and improved sapling tree selection.
...
- Choose the latest tree above the requested height
2020-01-15 07:35:02 -05:00
Kevin Gorham
596bea0158
Refactor to support new app.
2020-01-15 07:35:02 -05:00
Kevin Gorham
88aeb4f5ac
Correct hardcoded CoinType.
2020-01-15 07:35:01 -05:00
Kevin Gorham
b47b10427e
Blossom activation.
2020-01-15 07:35:01 -05:00
Kevin Gorham
8a365115f1
Add mainnet support.
...
This involves splitting code to run in the zcashMainnet and zcashTestnet flavors and using the corresponding feature of librustzcash. Mainnet functionality is proven in the integration test in androidTestZcashmainnet.
2020-01-15 07:35:01 -05:00
Kevin Gorham
5380c0d365
General cleanup before merging first pass at demo app.
2019-11-23 20:47:50 -05:00
Kevin Gorham
652e862d5c
Iterate on the Send demo.
...
Allow input. Allow multiple sends. Handle errors. Demonstrate an improved user experience where sending is disabled at the appropriate times.
2019-11-23 18:07:28 -05:00
Kevin Gorham
93d4114848
Refactor logic for awaiting confirmations.
...
Leverage the new flow-centric approach to sending transactions, rather than polling the database, which leads to concurrent modification errors and corrupted data.
2019-11-23 02:18:20 -05:00
Kevin Gorham
bebe0cf4e7
Rust welding utility functions for key derivation.
2019-11-20 18:23:20 -05:00
Kevin Gorham
7e9127538f
Update memo to accept bytes instead of a string.
2019-11-17 23:49:14 -05:00
Kevin Gorham
9cb178d6fb
Refactoring
2019-11-17 23:39:37 -05:00
Kevin Gorham
bf48b82aa8
Refactor package names
2019-10-24 01:21:52 -04:00
Kevin Gorham
f89d2be250
SDK changes to support new demo app.
...
- Convert status flags into stream of statuses, instead.
- Improve logging during transaction submission
- Database corrections. Aparently Room has gotten more strict with schema parsing and this required lots of corrections mainly around get nullability correct for DB fields.
- Simplify Synchronizer creation via constructor functions. Created one function for maximum simplicity and another for maximum flexibility.
- Changed logic for Wallet initialization to simplify dependencies and allow for optional access to private keys for wallet apps
- Created TransactionRepository that leverages the paging library for Room
- Provided sample implementation of bridging to a key manager in a way where wallet apps do not have to modify their existing code.
- Made it easier to clear the wallet data that can be repopulated from the blockchain
- Allowed for better cleanup of heavy-weight lightwalletd services by adding a shutdown API call
2019-10-24 01:16:58 -04:00
Kevin Gorham
190f7f5548
Consolidate old sample apps into new demo app.
2019-10-24 01:16:58 -04:00
Kevin Gorham
42f29f534c
Reduce configurability per Security Finding 1.
...
These changes largely reduce the amount of configuration that can be tweaked in order to prevent fragmentation of the anonymity set of users. If wallet makers change certain properties than it can become easy to detect which network requests are coming from which client. The goal is for clients to be as anonymous as possible.
2019-09-26 12:58:37 -04:00
Kevin Gorham
1f18042d52
Implement versioning and other cleanup.
...
- Correct typo and compiler warning in Rust.
'trait objects without an explicity dyn' are deprecated and this is a warning as of Rust 1.37
- update dependencies
- update documentation
docs
2019-09-12 01:31:23 -04:00
Kevin Gorham
636cbb59c0
Add TLS support.
...
Make TLS the default and require effort to setup plaintext connections, instead.
2019-09-12 01:31:22 -04:00
Francisco Gindre
28fa4d4ef2
add empty swift_prefix option value to .proto files
2019-08-30 14:52:14 -03:00
Kevin Gorham
a83ace6e43
Refactor after Zcon1
2019-08-30 10:07:56 -04:00
Kevin Gorham
8c7103d0ee
Cleanup after Zcon1.
2019-08-30 10:07:56 -04:00
Kevin Gorham
862a4be480
Pulled over classes from Zcon1 app.
...
Next step is to refactor and simplify.
2019-08-30 10:07:56 -04:00
Kevin Gorham
1de3ee9ed5
Added more fixes and examples for Zcon1.
...
Including unit tests that are more like utilities for doing interesting things.
2019-08-30 10:07:56 -04:00
Kevin Gorham
ad3a080466
Restore the memo sample to working order.
2019-08-30 10:07:56 -04:00
Kevin Gorham
54226997f9
Add sapling tree prior to Zcon1 token transactions.
2019-08-30 10:07:56 -04:00
Kevin Gorham
178f1d3a8d
Add support for raw transaction id.
...
This helps with mapping transactions when sweeping wallets.
2019-08-30 10:07:56 -04:00
Kevin Gorham
4dd8d408cb
Beginning to improve the use of channels.
...
Bringing over lessons learned from the Zcon1 app. There are a lot of changes to make, this is just the beginning of what was necessary to support that app.
2019-08-30 10:07:56 -04:00
Kevin Gorham
f222bde2fa
More robust error handling.
2019-08-30 10:07:56 -04:00
Kevin Gorham
305390b439
Update tests.
2019-08-30 09:59:29 -04:00
Kevin Gorham
94e2af7287
Improve error handling and troubleshooting by surfacing more errors.
2019-08-30 09:59:29 -04:00
Kevin Gorham
a78c98b8aa
Add more support for memos.
2019-08-30 09:59:29 -04:00
Kevin Gorham
4c635362a8
Add logic for handling reorgs and simplify synchronization.
2019-08-30 09:59:29 -04:00
Kevin Gorham
b14401eaeb
Twig: Add timing features and prevent duplicate tags.
2019-08-30 09:59:29 -04:00
Jack Grigg
f4843bc25d
More descriptive value errors in sendToAddress
2019-08-29 18:57:05 +01:00
Jack Grigg
221c882589
Migrate to note-spending-v6
2019-08-29 18:04:53 +01:00
Jack Grigg
09c51b7654
Update RecipientAddress to fix transparent address support
2019-07-10 14:55:38 -04:00
Jack Grigg
1acf472d33
RustBackend.isValid[Shielded|Transparent]Address()
2019-07-10 14:54:39 -04:00
Jack Grigg
54dbf8e0ff
Add transparent address send support to backend
2019-05-24 17:10:20 +01:00
Kevin Gorham
c3f57d5e2f
Rename JniConverter to RustBackend
...
Turns out JNI classes are hard to mock due to the way sytem libraries
are loaded. So it became easier to put the JniConverter class behind an
interface. Once that refactor was necessary, it was a good time to
update the name of this class because it retained its original PoC name
for far too long.
2019-05-24 16:33:43 +01:00
Jack Grigg
4948617d6d
Add JNI methods for handling chain validity and reorgs
2019-05-14 17:30:09 +01:00
Jack Grigg
0591784ce4
Add mainnet support to Rust backend via a feature flag
2019-05-14 17:10:03 +01:00
Jack Grigg
e69f4b6003
Migrate to refactored librustzcash branch
2019-05-14 17:10:03 +01:00
Kevin Gorham
7ec61df4a9
Changes to support memo sample
...
Mostly includes convenience functions for determining balance.
2019-04-24 03:16:15 -04:00
Kevin Gorham
30d36b723e
Improve logging behavior.
...
This simplifies the process of constructing an SdkSynchronizer.
2019-04-24 02:43:33 -04:00
Kevin Gorham
01b1ca1fed
Add KDocs to Synchronizer implementations and tidy their code
2019-03-30 00:20:32 -04:00
Kevin Gorham
7265a793c4
Restore tests to compiling
2019-03-29 02:05:45 -04:00
Kevin Gorham
72283cee81
Cleanup Synchronizer API, add KDocs and remove dead code
2019-03-29 02:04:25 -04:00
Kevin Gorham
796fe9602c
Update dependencies
2019-03-29 02:03:11 -04:00
Kevin Gorham
359e5c0adc
Clean up data API
...
Remove unused functionality and disable modification to tables that should only be written by librustzcash
2019-03-27 01:37:46 -04:00
Kevin Gorham
e7108ca818
Cleanup
...
This commit will get iteratively polished until the PR is ready
- Addresses PR feedback https://github.com/zcash/zcash-android-wallet-sdk/pull/16#discussion_r264948336
2019-03-27 01:37:46 -04:00
Kevin Gorham
b978bb5bc7
Update the logic for determining balance
2019-03-27 01:37:46 -04:00
Kevin Gorham
4aaf55f057
Add a layer of logic for bubbling up errors
...
This allows the app to show an error dialog rather than crashing silently
2019-03-27 01:37:46 -04:00
Kevin Gorham
17be0c85cb
Improve logic and behavior during app startup.
...
Never start downloading blocks prior to sapling activation height, only allow firstrun when dataDb is empty and also add birthday support. Also added corrections to isFirstRun logic.
2019-03-27 01:37:46 -04:00
Kevin Gorham
ef58fecbf1
Remove unused things and document limits of Junit 5 usage
...
It is not really practical to try and use JUnit 5 for Android Instrumentation tests at this time. See documentation in build.gradle for details.
2019-03-27 01:37:46 -04:00
Kevin Gorham
3efc91806a
Prevent change from being returned in transaction queries
2019-03-27 01:37:46 -04:00
Kevin Gorham
0ed5731ff4
Add address information to notes query and other cleanup
2019-03-27 01:37:46 -04:00
Kevin Gorham
4cbdd2ab27
Add additional logging to mock synchronizer
2019-03-27 01:37:46 -04:00
Kevin Gorham
82918dc09f
Twig: Refactor to be much more useful.
2019-03-27 01:37:46 -04:00
Kevin Gorham
ecff3ce588
Add conversion logic and extensions for consistency and correctness
...
Working with bigdecimals anytime we need to multiply or divide values because it was causing issues when repeatedly toggling currency on the send screen. Coupled this with lots of improvements on the app side to do less processing while changing currencies
2019-03-27 01:37:46 -04:00
Kevin Gorham
2132bc14fd
Fix bugs
2019-03-27 01:37:46 -04:00
Kevin Gorham
1b37784e44
Create mock synchronizer to help with driving the UI.
...
After experiencing several issues that make it more difficult to test send behavior, including the amount of time required to wait for blocks to get mined when testnet is slow,
it became obvious that it was time to investigate mocking. Most of the behavior in the SDK is driven by channels so the mock only has to focus on putting useful data in the
expected channels at the right time. One tradeoff here was the need to make all the synchronizer properties private, that way any implementation can achieve compatability
without necessasily leveraging the same combinations of building blocks. This tradeoff felt acceptable given that these dependencies can be injected and available as singletons,
if needed. This also had a side effect of elevating several channels into the Synchronizer interface, rather than reaching into the synchronizer to directly access those dependencies.
Another benefit is that it's now easier to see what matters most to the app, particularly which channels are essential.
2019-03-27 01:37:46 -04:00
Kevin Gorham
bf7b3ee744
Iterate and refine send and active transaction behavior
...
Send is now functional and shows up in active transactions.
This involved:
- reducing the exposure of the seed
- consistently using Ints for blockheight everywhere to match zcash
- adding the use of spending keys
- adding account initialization on startup
- using accounts but defaulting to account 0
- internalizing birthday so we no longer need a reference outside of the library
- enabling cancellation during send
- cleanup active transaction manager
2019-03-27 01:37:46 -04:00
Kevin Gorham
888646f73b
Create ActiveTransactionManager to monitor active transactions
...
When a transaction is sent it transitions through a lifecycle, beginning with creating the raw transaction and ending with it being mined and added to the blockchain
2019-03-27 01:37:46 -04:00
Kevin Gorham
4d226a8c5e
Create CompactBlockProcessor and refine responsibilities of collaborators
...
The synchronizer now primarily collaborates with a downloader, processor and repository; each with a more focused set of responsibilities.
The downloader streams blocks into a channel, the processor saves blocks from that channel and scans for transactions, the repository
exposes transaction change events.
2019-03-27 01:37:46 -04:00
Kevin Gorham
a871c5e476
Integrate with dataDb init commands and grpc service updates.
...
On the rust side, we now have access to the init DB commands. On the Go side we have time available for blocks
2019-03-27 01:37:46 -04:00
Kevin Gorham
57630f8eba
Create CompactBlockDownloader, iterate on business logic using new JUnit5 setup
...
streaming is working and tests are functional
2019-03-27 01:37:46 -04:00
Kevin Gorham
b688013f16
Switch to JUnit 5
2019-03-27 01:37:46 -04:00
Kevin Gorham
6c869a47df
Create synchronizer and add layer of business logic onto the data layer
...
App is functional and displays transactions
2019-03-27 01:37:46 -04:00
Kevin Gorham
1501f1a7d2
Add data access layer for dataDb
...
Update the scanBlocks request and integrate with the data that it generates inside dataDb
2019-03-27 01:37:46 -04:00
Jack Grigg
1474fae4b8
Move SQL backend into librustzcash
...
Also some tweaks due to error-handling changes in librustzcash.
2019-03-13 06:56:28 +00:00
Kevin Gorham
245841807c
add hex as required dependency, then use it inside init_blocks_table
2019-02-23 20:16:45 -05:00
Kevin Gorham
2c4a48b772
modify update_sapling_tree utility to output JSON
2019-02-22 10:04:32 -05:00
Kevin Gorham
148563b7e6
modify scan operation to start from sapling activation.
...
Rather than starting from zero because we do not need non-sapling blocks, prior to sapling's activation.
2019-02-22 10:04:32 -05:00
Jack Grigg
870283c8ea
JniConverter.getVerifiedBalance()
2019-02-19 01:45:38 +00:00
Jack Grigg
2a091a1da1
crate::sql::get_verified_balance()
2019-02-19 01:39:36 +00:00
Jack Grigg
4c901fc21f
Exclude spendable notes from selection that aren't verified
2019-02-19 01:25:25 +00:00
Jack Grigg
2695e8f6fd
Mark notes as unspent when the transaction they are spent in expires
2019-02-19 00:59:09 +00:00
Jack Grigg
273881c3b6
Re-introduce requirement that scanned blocks are height-sequential
...
This prevents the data DB from getting into a state where the Sapling
commitment tree is invalid, which was occurring too easily in testing.
2019-02-18 12:47:16 +00:00
Jack Grigg
d145091139
Debug logging in note selection
2019-02-18 12:31:57 +00:00
Jack Grigg
1cd1a4d2f1
Lock notes after transaction creation to prevent serial double-spends
...
Does not prevent parallel double-spends.
2019-02-18 12:27:14 +00:00
Jack Grigg
208a9497dd
Ensure we always select anchors from blocks that we have
2019-02-18 11:55:34 +00:00
Jack Grigg
b95f0b1fc9
Fix witness-updating bug, and enforce witness validity
2019-02-14 19:47:18 +00:00
Jack Grigg
966b6a9df5
Include fee in target value
2019-02-13 10:16:56 +00:00
Jack Grigg
e3ecc6f7dc
Fix underflow in target height when selecting anchor
...
This won't occur in practice because Sapling activated at a height well
above ANCHOR_OFFSET, but good to fix anyway.
2019-02-13 10:10:23 +00:00
Jack Grigg
6842c293fe
Ensure we have sufficient balance before using transaction::Builder
...
The Builder does return an error if insufficient spend value is
provided, but we can give a more meaningful error here.
2019-02-12 20:55:43 +00:00
Jack Grigg
9b29276dba
Return a more useful error if send_to_address() is called with no blocks
2019-02-12 20:49:35 +00:00
Jack Grigg
8eeddb2de0
Test that send_to_address() fails with incorrect ExtendedSpendingKeys
2019-02-12 19:46:16 +00:00
Jack Grigg
933fb07f42
Wrap all exceptions and panics to relay them over JNI
2019-02-12 02:56:17 +00:00
Jack Grigg
25e79f042b
Use failure::Error in utils::exception instead of jni::errors::Error
2019-02-11 16:52:00 +00:00
Jack Grigg
42b2076dc1
Add exception utilities to the crate
2019-02-11 16:35:44 +00:00
Jack Grigg
37c0efad77
Utilities for conveying Rust exceptions and panics to Java
...
Source: affa85c026/exonum-java-binding/core/rust/src/utils/exception.rs
License: Apache-2.0
2019-02-11 16:33:11 +00:00
Jack Grigg
6d86b2cf16
Extract rust_vec_to_java() utility function
2019-02-11 16:20:11 +00:00
Jack Grigg
5dfadd4393
Extract java_string_to_rust() utility function
2019-02-11 15:44:49 +00:00
Jack Grigg
1163c557a8
Use spending_key helper instead of manually constructing account path
2019-02-11 15:36:34 +00:00
Jack Grigg
886017a4f5
Migrate to Rust 2018 edition
...
Requires a minimum of Rust 1.31.
2019-02-11 15:11:09 +00:00
Jack Grigg
c4231fb404
Fix bug in collect() return type
2019-02-11 15:03:27 +00:00
Jack Grigg
eca0bbc697
Explicitly panic instead of unwrapping when an invariant is broken
2019-02-11 14:28:19 +00:00
Jack Grigg
e3ccb73a99
Remove unnecessary unwraps
2019-02-11 14:28:18 +00:00
Jack Grigg
d1c3c55b0d
Test that scan_cached_blocks finds change notes
2019-02-11 14:28:17 +00:00
Jack Grigg
70f9ab54c6
Simple binary to calculate the latest Sapling commitment tree
...
The gRPC Rust bindings are committed instead of requiring protoc to build.
2019-02-11 14:27:43 +00:00
Jack Grigg
b78a611f7b
JNI APIs to fetch memo fields as UTF8
2019-02-08 21:06:25 +00:00
Jack Grigg
6ae75baf35
Test that scan_cached_blocks finds received notes
2019-02-08 21:06:24 +00:00
Jack Grigg
e8eda3db33
Test that init_accounts_table stores the correct address
2019-02-08 21:06:23 +00:00
Jack Grigg
5dea1dbc04
Test that initialisation APIs are one-shot
2019-02-08 21:06:22 +00:00
Jack Grigg
8d9124fab5
Pass paths into the SQL API using AsRef<Path> instead of &str
...
This enables both &str and &Path to be used, depending on how the API is
being called.
2019-02-08 21:06:21 +00:00
Jack Grigg
45adb0af4a
Store creation time and expiry height in transactions table
...
- Creation time can be used in the UI before a transaction gets mined.
- Expiry height enables the UI to indicate expired transactions.
2019-02-07 14:39:50 +00:00
Jack Grigg
c51a90f4de
Fix clippy lints
2019-02-07 13:02:50 +00:00
Jack Grigg
acd8c395f3
Tidy up imports
2019-02-07 12:58:33 +00:00
Jack Grigg
a9674a148b
Remove cfg(target_os="android") restriction
...
The crate lives inside the Android SDK, and will only ever target
Android devices, so it's fine to simplify here.
2019-02-07 12:56:04 +00:00
Jack Grigg
e99ed5bdeb
Extract SQL API into a separate module
2019-02-07 12:50:40 +00:00
Kevin Gorham
66fff55967
bugfix: update JNI method signature to match implementation.
...
We removed the need to pass the seed around because that is highly sensitive data. Instead, we work with less sensitive sending keys.
2019-02-05 11:24:40 -05:00
Jack Grigg
62b4d43341
Remove seed argument from JniConverter.getAddress(), add account arg
2019-02-01 21:57:13 +00:00
Jack Grigg
b608b026ed
Remove seed argument from JniConverter.scanBlocks()
...
The API now scans cached CompactBlocks using the ExtendedFullViewingKeys
for the internally-tracked accounts.
2019-02-01 21:57:12 +00:00
Jack Grigg
d9232c885d
JniConverter.initAccountsTable()
2019-02-01 21:57:11 +00:00
Jack Grigg
c26249373d
JniConverter.initBlocksTable()
2019-02-01 21:57:10 +00:00
Jack Grigg
41bb9a1a4b
JniConverter.initDataDb()
2019-02-01 21:57:08 +00:00
Jack Grigg
aa391063d1
JniConverter.getBalance()
2019-02-01 21:57:07 +00:00
Jack Grigg
d98191d110
JniConverter.sendToAddress()
2019-02-01 21:57:06 +00:00
Jack Grigg
3966798f53
API for creating transactions
2019-02-01 21:57:05 +00:00
Jack Grigg
ab2b5903a0
Improvements to JniConverter.scanBlocks()
...
- Store Sapling tree with blocks
- Store witnesses with full notes
- Track note spends
- Track change notes
- Store index within block for each transaction
- This will make it easier to request entire blocks of transactions at
some point, and then filter out only the transactions we care about.
- Store block times while scanning blocks
- Return bool with error state from JniConverter.scanBlocks()
- Support cached blocks that are height-ascending but not sequential
- Blocks that do not contain Sapling data may be skipped.
- Return error from scan_cached_blocks() if heights are not ascending
2019-02-01 17:41:09 +00:00
Jack Grigg
3188cf8942
Remove now-unused ValueReceived protobuf
2019-01-31 16:09:37 +00:00
Jack Grigg
f622a3bcd8
Persist received notes in an SQLite database
2019-01-31 16:09:25 +00:00
Kevin Gorham
afc9a57d5d
checkpoint. DB works
...
Updated tests and found the root problem was with the SQL export,
meaning everything is actually working as expected.
2018-12-01 01:48:05 +00:00
Kevin Gorham
c9f11c6d2b
allow test to pass
2018-12-01 01:48:04 +00:00
Kevin Gorham
b499edd438
test scan blocks
2018-12-01 01:48:03 +00:00
Kevin Gorham
addcf60fc4
add error logging in Rust
...
This allows errors to bubble up to the android log file, rather than
having to sift through a tombstone file on the device.
2018-12-01 01:48:02 +00:00
Kevin Gorham
5df6e95e4f
saving and retrieving data is working and db files are generated
2018-12-01 01:48:01 +00:00
Kevin Gorham
72b594b0d0
added JNI test
...
I am a little excited about this because it will be a great way to test
Rust functionality quickly and iterate quickly because we will not have
to update and run the full app.
2018-12-01 01:48:00 +00:00
Kevin Gorham
241c646f14
checkpoint. data access object exists
2018-12-01 01:47:59 +00:00
Kevin Gorham
58f5a24a90
checkpoint. database exists
2018-12-01 01:47:58 +00:00
Kevin Gorham
81667f17cc
start with a test and maybe it will actually get used, Eventually.
2018-12-01 01:47:57 +00:00
Jack Grigg
83e00e1611
JniConverter.scanBlocks()
2018-12-01 01:47:41 +00:00
Jack Grigg
7bc3f2eede
Generate Rust protobuf representing received value
2018-12-01 01:46:35 +00:00
Jack Grigg
fc6c3c6b2b
Split address_from_seed to expose ExtendedFullViewingKey
2018-12-01 01:46:34 +00:00
Jack Grigg
6ab9c6610c
JniConverter.getAddress(seed)
2018-12-01 01:43:05 +00:00
Jack Grigg
193a1f3b22
cargo fmt
2018-11-21 13:51:37 +00:00
Kevin Gorham
19212b14c4
ignore unused variable
2018-11-21 02:04:06 -05:00
Kevin Gorham
32af4b9559
initial commit of sample project code
...
The next step is to clean this up and integrate it with the latest version of the android app
2018-11-20 12:59:08 -05:00