Compare commits

...

490 commits

Author SHA1 Message Date
Diego Salazar
e2014df4df
Merge pull request from cypherstack/staging
Staging
2025-04-17 10:25:32 -06:00
julian-CStack
2aedb15489
Merge pull request from Tritonn204/xelis-patch
Xelis Patch
2025-04-15 15:30:08 -06:00
Tritonn204
aa53690f06 switched back to native path separators for Xelis 2025-04-15 12:42:26 -07:00
Tritonn204
89f55c7fec remove libtinfo5.deb 2025-04-15 10:40:07 -07:00
Tritonn204
6aa6b8c950 gitignore fix 2025-04-15 10:39:18 -07:00
Tritonn204
7f69eb8eff git commit -m "Stop tracking Microsoft.Windows* files and folders" 2025-04-15 10:39:07 -07:00
Tritonn204
f45f8cfa76 updated gitignore 2025-04-15 10:36:37 -07:00
Tritonn204
7c408a1af6 updated to xelis_flutter v0.1.1 2025-04-14 21:32:20 -07:00
Tritonn204
13d23a42e3 tx fee fully fixed 2025-04-14 20:08:37 -07:00
Tritonn204
a4de7d34cc windows secp script fix 2025-04-14 13:45:37 -07:00
Tritonn204
27dd2a2134 moved to org xelis repo 2025-04-14 12:29:37 -07:00
Tritonn204
422c191e65 windows secp script fix 2025-04-14 12:27:57 -07:00
Tritonn204
56bcc23c74 fixed path separator on windows, decouple fee calculation from transfer count in TX history 2025-04-14 11:58:03 -07:00
julian
b435838dc3 fix bad patch 2025-04-01 17:19:03 -06:00
julian-CStack
6534bf62dd
Merge pull request from cypherstack/spark-win-fix
update spark ref and coinlib with win build fix
2025-04-01 14:13:48 -06:00
julian
29416bdfc6 update spark ref and coinlib with win build fix 2025-04-01 14:12:21 -06:00
julian-CStack
f43a0ba97d
Merge pull request from cypherstack/ios-min-ver-ref
update liblelantus ref
2025-03-29 12:07:16 -06:00
julian
d9acb6728a update liblelantus ref 2025-03-29 12:06:29 -06:00
julian-CStack
906c2c3a97
Merge pull request from cypherstack/cargo_ndk_3
Cargo ndk 3
2025-03-28 11:39:54 -06:00
julian
913a4ac7c5 add explicit cast and type check 2025-03-28 11:38:20 -06:00
julian
d2e77c9ff0 handle nanswaps api response change 2025-03-28 11:32:22 -06:00
julian
93212d7970 update merged refs 2025-03-28 11:08:31 -06:00
julian
cfba818f12 temporary git ref updates for testing 2025-03-28 11:03:51 -06:00
julian
ce639c9955 docs update 2025-03-28 11:03:51 -06:00
julian-CStack
a1b4a35180
Merge pull request from Tritonn204/xelis
Xelis new TX type handling fix
2025-03-28 07:44:05 -06:00
julian-CStack
86e8c38266
Merge branch 'staging' into xelis 2025-03-28 07:43:44 -06:00
Tritonn204
321ae2e7ad New TX typing bug fix for 2025-03-27 23:44:09 -05:00
julian-CStack
fcc2df5e5b
Merge pull request from cypherstack/back2multi_rust
revert to switching rust versions as required
2025-03-27 14:20:57 -06:00
julian
5bb7813234 revert to switching rust versions as required 2025-03-27 14:19:33 -06:00
julian-CStack
02fec3d581
Merge pull request from cypherstack/gradle_ndk
Gradle ndk
2025-03-27 11:01:47 -06:00
julian
3251159814 update docs re rust version 2025-03-27 10:58:28 -06:00
julian
a62b58041a clean up scripts 2025-03-27 10:43:31 -06:00
julian
72fa218a98 update liblelantus 2025-03-27 09:39:03 -06:00
julian
ec2777b9ff update coinlib and sparkmobile 2025-03-26 17:49:38 -06:00
julian-CStack
65e6c50a66
Merge pull request from cypherstack/epic
fix: Epic on Android, use NDK 28
2025-03-26 17:48:17 -06:00
sneurlax
6f8c6003d1 fix: Windows Epic example and build scripts 2025-03-26 23:47:14 -05:00
sneurlax
dabb2aa1b3 fix: update scripts and docs re: rust verion, ie 1.67.1->1.81 2025-03-26 15:11:54 -05:00
sneurlax
d789ae120b feat: use NDK 28, fix epic on android, remove automatic cbindgen use 2025-03-26 15:11:49 -05:00
julian
815c16a736 NDK and gradle updates 2025-03-26 09:32:26 -06:00
julian-CStack
f1014a6c78
Merge pull request from detherminal/staging
feat: detect bitcoin/monero uri's
2025-03-24 15:40:08 -06:00
dethe
3fbc6daba0 feat: use _applyUri for paste 2025-03-22 01:30:36 +03:00
dethe
15a7a34ece
Merge branch 'cypherstack:staging' into staging 2025-03-21 21:18:08 +03:00
julian-CStack
3118968230
Merge pull request from cypherstack/xelis
Xelis
2025-03-20 20:48:55 -06:00
Julian
37f318a902 linting, formatting, small cleanups, and an extra logging call 2025-03-20 20:47:10 -06:00
Tritonn204
42d7275b51 removed print 2025-03-20 21:32:44 -05:00
julian-CStack
7cf966c443
Merge pull request from Tritonn204/xelis
Xelis bug fixes
2025-03-20 20:28:42 -06:00
Tritonn204
03f4b2fdea removed init finally{} block for Xelis 2025-03-20 21:22:51 -05:00
Tritonn204
4431d8c689 re-enabled null checks for Xelis afer open() 2025-03-20 19:55:46 -05:00
Anthony Tritonn
50163b5d19
Merge branch 'cypherstack:xelis' into xelis 2025-03-20 17:50:48 -07:00
Tritonn204
78b4e2d6b7 Added initCompleter for Xelis 2025-03-20 19:50:01 -05:00
julian-CStack
22ff0b1709
Merge pull request from Tritonn204/xelis
Xelis init/open refactor
2025-03-20 14:35:58 -06:00
Tritonn204
e18a254f0c Merge branch 'xelis' of https://github.com/Tritonn204/stack_wallet into xelis 2025-03-20 15:11:41 -05:00
Tritonn204
ae0631adeb reversed investigative changes 2025-03-20 15:11:37 -05:00
Anthony Tritonn
302ceaaf1f
Merge branch 'xelis' into xelis 2025-03-20 13:00:16 -07:00
Tritonn204
176ed0f89f Xelis init/open refactor 2025-03-20 14:51:12 -05:00
Julian
a503861c0f Merge remote-tracking branch 'origin/staging' into xelis 2025-03-20 12:02:00 -06:00
julian-CStack
b32ec57a8d
Merge pull request from cypherstack/epic
flutter_libepiccash update: reorganize Rust wrapper, add tests, fix example app
2025-03-20 12:00:58 -06:00
sneurlax
87101c86c2 Merge remote-tracking branch 'origin/staging' into epic 2025-03-20 12:57:07 -05:00
sneurlax
8c48930feb fix: update flutter_libepiccash to main 2025-03-20 12:56:41 -05:00
Julian
e4ac7d8569 add missing continue; 2025-03-20 11:34:50 -06:00
Julian
65782bb711 Merge remote-tracking branch 'origin/staging' into xelis 2025-03-20 11:34:22 -06:00
julian-CStack
574d0e82ff
Merge pull request from cypherstack/apple_updates
Apple updates
2025-03-20 11:30:15 -06:00
Julian
fe43785546 more logging 2025-03-20 10:04:16 -06:00
Julian
f77950de68 ensure fee amount is formatted correctly to String 2025-03-20 07:53:38 -06:00
julian-CStack
e07d878eae
Merge pull request from Tritonn204/xelis
Xelis Polish
2025-03-19 15:52:25 -06:00
Tritonn204
8f5d17d026 close on restore for all ExternalWallet instances 2025-03-19 16:31:50 -05:00
Tritonn204
a40fdfecda Merge branch 'xelis' of https://github.com/cypherstack/stack_wallet into xelis 2025-03-19 13:07:25 -05:00
Tritonn204
6e04f8e34d Xelis updates. configured Unix line endings repo-wide 2025-03-19 13:07:14 -05:00
Julian
2298a12afb update themes 2025-03-18 14:48:22 -06:00
Julian
6361d9f048 WIP: wallet exists check 2025-03-18 09:05:11 -06:00
Julian
ce5d9d43e1 use Platform.pathSeparator 2025-03-18 09:04:50 -06:00
dethe
d835b14230 fix: controller positioning 2025-03-18 13:31:28 +03:00
dethe
1cddb14bf1 feat: detect bitcoin/monero uri's
fix: use uri instead of manual parsing

reformat: remove braces and use efficient variables

refactor: add forgotten vars
2025-03-18 13:15:55 +03:00
Julian
5adfee831e Use logger 2025-03-17 17:19:07 -06:00
Julian
b3e02b64de use standard app dir 2025-03-17 17:16:05 -06:00
Julian
564c3ba715 update default themes 2025-03-17 17:14:05 -06:00
sneurlax
441bc8c113 feat: update flutter_libepiccash
TODO: merge https://github.com/cypherstack/flutter_libepiccash/pull/56 "Reorganize codebase, add tests, and fix example app" to main
2025-03-17 17:00:45 -05:00
Julian
8e703f128c temp libspark fix 2025-03-17 14:28:38 -06:00
Julian
c24935dabf logging change 2025-03-17 12:01:53 -06:00
Julian
fe2514e97e lint and code formatting 2025-03-17 08:42:32 -06:00
Julian
b190907cae pubspec lock update 2025-03-17 08:25:41 -06:00
Julian
e39c817ec5 Merge remote-tracking branch 'origin_sw/apple_updates' into xelis
# Conflicts:
#	ios/Podfile.lock
2025-03-17 08:14:50 -06:00
julian-CStack
6b33aee103
Merge pull request from Tritonn204/main
Initial Xelis integration
2025-03-17 08:08:40 -06:00
Julian
30dedee63f ios tweaks and updates 2025-03-17 07:59:13 -06:00
Tritonn204
6e725a5bb5 removed comment 2025-03-14 20:51:14 -07:00
Tritonn204
4feb14c7da updated rust logging method, added mnemonic word validation for Xelis 2025-03-14 20:51:00 -07:00
Tritonn204
0f7e44fadd rebase cleanup + xelis bug fixes 2025-03-14 14:38:05 -07:00
Julian
08c5a5fbc7 macos tweaks and updates 2025-03-13 17:50:56 -06:00
Tritonn204
0d20cb6b3b remove logging package from test_node_connection 2025-03-13 16:17:32 -07:00
Tritonn204
dd67d2fdbb reversions and deletions as per request 2025-03-13 16:17:32 -07:00
Tritonn204
f7b73620e2 added port information to xelis connection invocations 2025-03-13 16:17:32 -07:00
Tritonn204
4e26e4c246 updated dep template 2025-03-13 16:17:32 -07:00
Tritonn204
c1cd9869c0 removed xelis submodule in favor of git tag dependency 2025-03-13 16:17:13 -07:00
Tritonn204
448fd0c94d keep version update without frostdart in windows build scripts 2025-03-13 16:17:13 -07:00
Tritonn204
0ed0ef3ed9 removed frostdart from windows build scripts 2025-03-13 16:17:13 -07:00
Tritonn204
f56519ec14 svg change reversal 2025-03-13 16:17:13 -07:00
Tritonn204
8c6f660ec6 libepiccash build script corrections, pubspec template adjusted for staging 2025-03-13 16:17:13 -07:00
Tritonn204
2879e5bc03 updated fee estimation params in xelis_flutter 2025-03-13 16:17:13 -07:00
Tritonn204
a06945b3a2 xelis_flutter correction 2025-03-13 16:17:13 -07:00
Tritonn204
8b41d0b588 xelis_flutter branch switch adopted 2025-03-13 16:17:13 -07:00
Tritonn204
102fab5fae updated price_test, corrected outgoing tx db entries for xelis 2025-03-13 16:17:13 -07:00
Tritonn204
0dad4ad591 updated linux devops for new Xelis flutter setup, fixed Xelis fee estimation bug 2025-03-13 16:17:13 -07:00
Tritonn204
2f02d4dc58 removed Xelis lib from build scripts 2025-03-13 16:17:13 -07:00
Anthony Tritonn
e04efc7247 Apple/iOS builds working (with PRs from plugins) 2025-03-13 16:17:02 -07:00
Anthony Tritonn
1463ea7972 Xelis price service added, wallet storage bugs fixed, updated to apple-compliant xelis lib 2025-03-13 16:16:52 -07:00
Tritonn204
e1964ea68e adjusted for xelis flutter refactor 2025-03-13 16:16:24 -07:00
Tritonn204
c6bff81648 Android works 2025-03-13 16:16:24 -07:00
Tritonn204
7a3558e7e9 Slight polish for Xelis integration 2025-03-13 16:16:24 -07:00
Tritonn204
24a20238bc Xelis base integration 2025-03-13 16:16:24 -07:00
Tritonn204
96478de9cc gitignore 2025-03-13 16:10:37 -07:00
Tritonn204
5f9466ca3c build script + dep updates, xelis library integration progress 2025-03-13 16:10:37 -07:00
Tritonn204
34cee82018 added xelis enum variants 2025-03-13 16:07:30 -07:00
Tritonn204
2061eba2f2 xelis CryptoCurrency definition added, bridged wallet wrapper started 2025-03-13 16:07:30 -07:00
Tritonn204
2edfe0f3cc xelis boiler plate early setup 2025-03-13 16:07:30 -07:00
Julian
709eebc1b7 update frostdart submodule 2025-03-13 16:06:31 -06:00
Julian
dbc805ed21 update liblelantus submodule 2025-03-13 14:55:37 -06:00
julian-CStack
7439dbf9fc
Merge pull request from detherminal/staging
fix: use trocador provider icons
2025-03-13 11:24:14 -06:00
dethe
bf5bfc3d71 fix: use trocador provider icons 2025-03-12 23:51:29 +03:00
julian
60d47f235d update sparkmobile lib 2025-02-26 16:32:59 -06:00
julian
48d2ac5e9b firo desktop wallet header refactor 2025-02-26 16:32:59 -06:00
julian
3146f4dce9 WIP firo balance display desktop 2025-02-26 16:32:59 -06:00
julian
5ddde67555 hide zero lelantus balance on desktop 2025-02-26 16:32:59 -06:00
julian
fd223ddaea android build files ignore 2025-02-25 11:47:07 -06:00
julian
03dcb2babf update barcode_scan2 for flutter 3.29.0 2025-02-25 11:47:07 -06:00
julian
44f0d0d8df flutter_libmonero is no more 2025-02-25 11:47:07 -06:00
julian
ed65ab5648 flutter version update 2025-02-25 11:47:07 -06:00
julian
29802ddda5 update name functionality w/ basic json pretty view 2025-02-25 08:32:53 -06:00
julian
7dd919f795 disable manage for pre reg names for now 2025-02-25 08:32:53 -06:00
julian
6539b75f9f mobile/desktop name ui clean up and transfer name functionality 2025-02-25 08:32:53 -06:00
julian
05767dea13 name tx note tweaks 2025-02-25 08:32:53 -06:00
julian
9fc6368644 WIP: manage domain ui 2025-02-25 08:32:53 -06:00
julian
edaaeda838 clean up domain names management ui somewhat 2025-02-25 08:32:53 -06:00
julian
ae97d3ce24 domain name input length restriction 2025-02-25 08:32:53 -06:00
julian
a576e45199 WIP: namecoin names desktop/mobile specific layout tweaks, and various clean up 2025-02-25 08:32:53 -06:00
julian
ad07d7abb9 fix: pop buy name dialog on success 2025-02-25 08:32:53 -06:00
julian
0d1bfc191f clean up logging 2025-02-25 08:32:53 -06:00
julian
06b0584691 better encoding 2025-02-25 08:32:53 -06:00
julian
7cdbe581ef show error dialog 2025-02-25 08:32:53 -06:00
julian
116b5747cf validate name value length 2025-02-25 08:32:53 -06:00
julian
63474ac6eb better base dialog widget 2025-02-25 08:32:53 -06:00
julian
321cf855a7 clean up record info display 2025-02-25 08:32:53 -06:00
julian
51b0cc1510 add method to check for and ignore name outputs in balance 2025-02-25 08:32:53 -06:00
julian
cd9907db5c WIP: namecoin domain name buy and add record ui 2025-02-25 08:32:53 -06:00
julian
667f2f504e change particl default address type to old 2025-02-25 08:32:53 -06:00
julian
f1e1bd0dc0 WIP names gui 2025-02-25 08:32:53 -06:00
julian
534ee51275 update namecoin dns More option name and icon 2025-02-25 08:32:53 -06:00
julian
cdffec81df refactor auto register NAME NEW process 2025-02-25 08:32:53 -06:00
julian
69b3e9b1ab handle name op output selection based on name op type 2025-02-25 08:32:53 -06:00
julian
6d291408a3 hack in name op utxo confirmation check 2025-02-25 08:32:53 -06:00
julian
873fc63045 consistent log level edit 2025-02-25 08:32:53 -06:00
julian
5a39bb2b64 auto focus cursor in search field on desktop 2025-02-25 08:32:53 -06:00
julian
3ea469bb1f use private key for deterministic salt 2025-02-25 08:32:53 -06:00
julian
c277cd9641 update namecoin_dart version 2025-02-25 08:32:53 -06:00
julian
0623023b3a WIP names 2025-02-25 08:32:53 -06:00
julian
2e737b5911 build runner update mocks 2025-02-25 08:32:53 -06:00
julian-CStack
5169dfd7fe
Merge pull request from cypherstack/sneurlax-patch-1
Replace `vapigen` with `valac` in Ubuntu 20.04 build docs
2025-02-25 07:36:11 -06:00
julian-CStack
1c6b84c823
Merge branch 'staging' into sneurlax-patch-1 2025-02-25 07:35:52 -06:00
sneurlax
56314e7f24
Replace vapigen with valac for Ubuntu 20.04 build docs
If `valac` works, merge this PR.
2025-02-23 19:05:56 -06:00
julian
024086910b log some extra wallet info 2025-02-06 12:14:10 -06:00
julian
8ca4421c2a adjust log level privacy warning text 2025-02-06 12:14:10 -06:00
julian
694910ab18 replace deprecated logd function, clean up some logging and fix some log level logging levels 2025-02-06 12:14:10 -06:00
julian-CStack
2dfacd42c5
Merge pull request from cypherstack/logging
Logging
2025-02-05 17:22:24 -06:00
julian
c4db10c9d3 add deprecated message 2025-02-05 17:12:44 -06:00
julian
4589e42ac8 refactor log function name 2025-02-05 17:07:49 -06:00
julian
68c7ba6910 log level preference 2025-02-05 17:01:40 -06:00
julian
176f0ba331 clean up some prints and use logging instead in some places 2025-02-05 14:57:55 -06:00
julian
b9ed3ae0a0 update file_picker 2025-02-05 14:47:56 -06:00
Julian
452f4a7daa macos file entitlements for updated file picker to allow SWB save/load 2025-02-05 14:08:45 -06:00
Julian
b05f664088 disable logs location selection on macos for now 2025-02-05 13:48:47 -06:00
julian
de047339f8 WIP updated logging 2025-02-05 11:31:57 -06:00
julian
90e421174a option to rescan on lelantus scanning enable 2025-01-31 12:50:40 -06:00
julian
75f6e65fd9 expose firo advanced features in dev options 2025-01-31 12:50:40 -06:00
julian
1d9b2e39fe update trocador api 2025-01-31 12:50:40 -06:00
julian
6c31e4662d desktop single coin wallet delete ui fix 2025-01-31 12:50:40 -06:00
Julian
1a3a09a325 firo balance type button changes 2025-01-31 12:50:40 -06:00
Julian
ab450684b2 clarify checking of new/unmined spark coins 2025-01-31 12:50:40 -06:00
Julian
9bd343c987 obscure seed words while restoring in progress 2025-01-31 12:50:40 -06:00
Julian
128dc14ce7 update min flutter/dart sdk 2025-01-31 12:50:40 -06:00
julian
cb11d58c47 fix: double encoded qr address prefix 2025-01-15 15:17:08 -06:00
julian
1a094d3745 update test 2025-01-14 16:55:25 -06:00
julian
a01dce1c72 Only fetch full monero transactions via ffi if required 2025-01-14 16:55:25 -06:00
julian
38e66bfcb1 chore: update pubspec.lock 2025-01-13 17:17:34 -06:00
julian
0d1bf5895d fix: incorrect number of confirms for monero (and wownero) outputs and transactions 2025-01-13 17:17:34 -06:00
julian-CStack
ad667025ac
Merge pull request from singpolyma/fastlane
Add fastlane metadata
2025-01-13 15:07:37 -06:00
julian-CStack
e7ad498b71
Merge branch 'staging' into fastlane 2025-01-13 15:07:21 -06:00
julian-CStack
975fe733f0
Merge pull request from Cyrix126/fix_1061
fix: Login/Password of Node dialog can't be made empty after setting a value
2025-01-13 14:35:34 -06:00
julian-CStack
22f9d4c653
Merge branch 'staging' into fix_1061 2025-01-13 14:35:20 -06:00
Louis-Marie Baer
130895a449 fix: update logins even if null 2025-01-13 20:35:24 +01:00
julian-CStack
2aa548e3e0
Merge pull request from Cyrix126/node_auth
handle authentication in test of monero nodes
2025-01-13 13:09:55 -06:00
julian-CStack
4c7cb0c309
Merge branch 'staging' into node_auth 2025-01-13 13:09:23 -06:00
Louis-Marie Baer
b44cde334c fix: no 24 words option for restoring namecoin wallet 2025-01-06 09:46:36 -06:00
Louis-Marie Baer
516b503f31 use monero_rpc from pub dev 2024-12-27 20:19:33 +01:00
Louis-Marie Baer
1137b50b8a fix: 2024-12-26 13:56:37 +01:00
Louis-Marie Baer
d64c344fd0 feat: handle test monero node authentication 2024-12-24 17:00:19 +01:00
julian
4fc2a7acfa fix: optional cast error 2024-12-17 19:27:49 -06:00
julian
ba1ab977d6 chore: build runner 2024-12-17 16:37:22 -06:00
julian
0e32e8a408 fix: Issue where spark spend may not have appeared as confirmed 2024-12-17 16:37:22 -06:00
julian
f97ef50978 fix: update hash format and use better sector/page size 2024-12-17 16:37:22 -06:00
julian
4439ad70d2 fix: incremental spark data cache 2024-12-17 16:37:22 -06:00
julian
2028505367 fix: spark coin confirmations issue 2024-12-17 16:37:22 -06:00
julian
1884bfbaf7 fix: tweak sync percent feature and track progress during spark anon set download 2024-12-17 16:37:22 -06:00
julian
c1ef98833a reduced pings 2024-12-17 16:37:22 -06:00
julian
ae10bef0ee fix: updated spark data calls and caching 2024-12-17 16:37:22 -06:00
julian
d6aec00b58 WIP: paginated spark anon set prep 2024-12-17 16:37:22 -06:00
julian
744f273862 WIP: fix electrumx failovers, add some "default" firo nodes, and tweak firo pings 2024-12-17 16:37:22 -06:00
Diego Salazar
34ad1d9022
Merge pull request from cypherstack/julian
Various
2024-12-13 10:52:03 -07:00
julian
e9aa2d6a30 fix: force override of a dep we don't even use so that sqlite doesn't complain 2024-12-12 17:26:55 -06:00
julian
eeb595e0d9 fix: Update device-locale dep version to handle linux crashes with certain locale configurations 2024-12-12 17:05:58 -06:00
julian
2e0ac0b2f5 chore: extra logging 2024-12-12 16:58:01 -06:00
julian
c56038cadf fix: Prevent failed keys fetch from disabling display of mnemonic 2024-12-12 16:54:55 -06:00
julian
9c64ed6316 chore: update deps 2024-12-12 16:53:21 -06:00
julian
120952156f fix: Linux qr scan would previously load the last scanned data if it exists 2024-12-11 18:20:44 -06:00
julian
3adddc2368 fix: possible race condition when processing desktop qr data by returning the result on pop rather than using a callback, clean up some linter stuff, and prevent calling setState in dispose 2024-12-11 17:40:22 -06:00
julian
e749c62ccd chore: satisfy linter 2024-12-11 16:41:00 -06:00
julian
cdf2dd8819 feat: xmrrpc (and wowrpc) node uri scanning ui for adding new nodes 2024-12-11 15:26:12 -06:00
julian
4af7243265 feat: xmrrpc (and wowrpc) uri parsing + tests 2024-12-11 11:54:14 -06:00
julian
2873595e40 chore: use libsecret mirror due to instability of gitlab.gnome.org 2024-12-11 09:24:42 -06:00
julian
71609c34b0 feat: allow setting the restore/refresh height in xmr/wow wallets 2024-12-10 14:51:37 -06:00
julian
937550cb04 fix: xmr/wow node connection was replacing onion addresses with an empty string 2024-12-09 16:29:02 -06:00
julian
fed7ae91d9 fix: frost reshare issue when initiator is a new participant of a 1/2 config 2024-12-09 15:29:25 -06:00
julian
e9252a4d46 fix: ensure xmr/wow transactions updated on balance changed 2024-12-09 13:07:56 -06:00
julian
ec1b5d7d2b fix: propagate restore errors correctly. Should fix https://github.com/cypherstack/stack_wallet/issues/1047 2024-12-09 10:37:39 -06:00
julian
4a59505c30 fuzzy logic. Better safe than sorry 2024-12-05 00:40:59 -06:00
julian
3f8cf2583c disable wownero 14 word seeds 2024-12-05 00:40:59 -06:00
julian-CStack
9eb233ec76
Merge pull request from cypherstack/tx-key
xmr/wow show tx spend key option
2024-12-04 11:01:44 -06:00
julian
cd068eefc7 xmr/wow show tx spend key option 2024-12-04 11:00:22 -06:00
julian-CStack
a74c565f9a
Merge pull request from cypherstack/frost-init-fix
Various fixes and tweaks
2024-12-03 16:24:21 -06:00
julian-CStack
465a8b4c96
Merge branch 'staging' into frost-init-fix 2024-12-03 16:24:03 -06:00
julian
c3a64b154b No idea why this was changed but it causes problems so I am reverting it 2024-12-03 16:21:01 -06:00
julian
64dd830e58 fix new xmr/wow wallet creation when specifying mnemonic length 2024-12-03 16:21:01 -06:00
julian
86e3bf0349 improve SWB restore performance when a large number of wallets is involved 2024-12-03 15:00:25 -06:00
julian
840b6f9c99 fix mnemonic blank on mobile back up screen 2024-12-03 14:41:56 -06:00
julian-CStack
9f0f94b29b
Merge pull request from cypherstack/staging
Staging
2024-12-03 12:45:48 -06:00
julian-CStack
3266e4e055
Merge branch 'main' into staging 2024-12-03 12:45:36 -06:00
julian
925b58be50 fix frost wallet init address error 2024-11-29 17:05:35 -06:00
julian
9e988b8ba5 fix restoring of xmr/wow wallets during swb restore process 2024-11-28 14:36:45 -06:00
julian
dbf68f2a68 hide exchange toggle on disabled platforms 2024-11-28 08:29:28 -06:00
Diego Salazar
1ce4bee68c
Merge pull request from cypherstack/node-settings
Node settings
2024-11-26 13:29:33 -07:00
julian
d6abd7d658 "handle" null account info according to https://solana.com/docs/rpc/http/getaccountinfo#result 2024-11-26 13:48:33 -06:00
julian
3fb18bf2db info dialog if node settings and current TOR status will cause sync issues on wallet open 2024-11-26 12:46:18 -06:00
julian
b548386097 hack a check for node tor settings before making calls into tezos as well 2024-11-26 10:45:08 -06:00
julian
800de8873d check stellar node tor setting before making calls 2024-11-26 10:37:39 -06:00
julian
cd003ba412 check solana node tor setting before making calls 2024-11-26 10:31:23 -06:00
julian
7d047e8d47 fix solana node update logic 2024-11-26 10:30:49 -06:00
julian
31fe9a538b hack in a tor check to nano and banano 2024-11-26 10:14:02 -06:00
julian
d87af969d6 eth doesn't do tor due to underlying lib limitation. 2024-11-26 10:07:14 -06:00
julian
25c6c7590b fix layout overflow on desktop 2024-11-26 10:06:47 -06:00
julian
8a63c42582 badly hack tor node settings into epic wallets 2024-11-26 10:00:56 -06:00
julian
7b603cd7f9 make cardano aware of tor node settings 2024-11-26 09:44:52 -06:00
julian
4197ff40f4 consistent variable naming 2024-11-26 09:18:35 -06:00
julian
d6d4df7822 quick (quite quick) and dirty (very dirty) tor/clearnet/both config option for coin network/node connections 2024-11-25 18:29:58 -06:00
julian
6cfe9e9c0f add plain/tor network flags to node data 2024-11-25 13:33:58 -06:00
Diego Salazar
f38efd35e9
Merge pull request from cypherstack/paynym-changes
Various changes
2024-11-22 15:51:23 -07:00
julian
d8ec93fb30 add copy button to txid field in tx details on mobile 2024-11-22 15:15:09 -06:00
julian
537e44f1f8 modify default themes install/loading/checks. Should fix missing ada (or sol?) icon 2024-11-22 13:31:16 -06:00
julian
2431d5f300 churn gif 2024-11-22 13:15:07 -06:00
julian
9a2589b4c3 disable segwit paynym claiming and disable follow/unfollow due to server token signing not working 2024-11-22 13:01:23 -06:00
julian
7511ce2ac3 Enable frost on desktop. Not sure why it was disabled. I guess we'll find out soon enough if there are issues... 2024-11-22 12:58:48 -06:00
julian
973d8b3eee update liblelantus for linux openssl linking fix 2024-11-21 17:23:58 -06:00
julian
6dd7ef183a fix probable infinite loop causing view only refresh to stay stuck forever 2024-11-21 14:43:05 -06:00
julian
216719ba56 fix gui overflow issues 2024-11-21 12:31:59 -06:00
julian
91de7ddbc0 show 0 fee for coinbase transactions 2024-11-21 12:31:59 -06:00
julian
0ce0350039 fix parsing of coinbase utxos 2024-11-21 12:31:59 -06:00
julian
db7422a100 update libepiccash and fix odd address error caused by some odd code 2024-11-21 11:22:08 -06:00
julian
9c9a9f8d3e ensure tx status label shows correct number of confirms if is coinbase 2024-11-21 10:01:03 -06:00
julian
40b0f49f20 add functionality for different number of required min confirms for coinbase transactions and apply to firo 2024-11-21 10:01:03 -06:00
julian
3566d75d58 Do token balance check before allowing send and fix some amount formatting bugs 2024-11-21 09:19:07 -06:00
julian-CStack
31e785c23f
Merge pull request from cypherstack/ubuntu-24.04
Ubuntu 24.04 support
2024-11-20 18:14:02 -06:00
julian
6c42da2add use updated spark lib 2024-11-20 16:57:33 -06:00
julian
f41a85bd6e Merge remote-tracking branch 'origin/staging' into ubuntu-24.04
# Conflicts:
#	crypto_plugins/flutter_libmonero
#	docs/building.md
#	pubspec.lock
#	scripts/app_config/templates/pubspec.template
#	scripts/linux/build_secp256k1.sh
#	scripts/windows/deps.sh
2024-11-20 11:47:17 -06:00
julian
ae9a844ed8 remove patchception 2024-11-20 11:40:57 -06:00
julian
4594801cf3 Ensure plain addresses are parsed from qr codes. Use uri parsing everywhere with a couple small tweaks. 2024-11-19 09:25:26 -06:00
julian
f15d051108 update solana package 2024-11-19 09:25:26 -06:00
julian
5496d2de96 allow "," decimal separator in qr code generator 2024-11-19 09:25:26 -06:00
Stephen Paul Weber
0d8df43d97
Add fastlane metadata
For 
2024-11-15 11:23:22 -05:00
julian
b84c3ab2d3 update cs_monero dep 2024-11-15 09:49:41 -06:00
Julian
6494bec72b lock sqlite version 2024-11-14 18:13:05 -06:00
julian
48d46cd18c fix for adding certain eth tokens 2024-11-14 16:55:49 -06:00
julian
f2a654e1e5 disable syncing of newly created view only wallet without entering the wallet first 2024-11-14 16:55:49 -06:00
julian
1d22eed7c4 disable paynym in view only wallets ui 2024-11-14 16:55:49 -06:00
julian
44f9886ffd use address type implied by derivation path in view only wallets 2024-11-14 16:55:49 -06:00
julian
3177fadea6 fix back up views 2024-11-14 16:55:49 -06:00
julian
5452598064 fix duplicate assignment 2024-11-14 16:55:49 -06:00
julian
98d77621b2 disable spark and lelantus features in view only wallets for the time being 2024-11-14 16:55:49 -06:00
julian
e95d5a10b6 update paynym url 2024-11-14 16:55:49 -06:00
julian
6ff539e71b Add support for view only wallets to most coins 2024-11-14 16:55:49 -06:00
julian
3da57bc150 fix: receive view bug 2024-11-14 16:55:49 -06:00
julian
1f0ee995b9 ui view only wallet changes 2024-11-12 18:13:37 -06:00
julian
53eb6ac8d1 monero (and wow) view only wallet functionality 2024-11-12 18:13:37 -06:00
julian
3d2d0e4e73 feat: go directly into wallet if only a single wallet exists for the specified currency on desktop 2024-11-12 18:13:37 -06:00
julian
0080d25436 fix: clean up and fix some churning stuff 2024-11-12 18:13:37 -06:00
julian
9cde0a1f65 feat: rough "churning" for xmr/wow 2024-11-12 18:13:37 -06:00
julian
a03b0ec2aa update to cs_monero 1.0.0-pre 2024-11-05 18:54:13 -06:00
julian
016a53f8eb get rid of a submodule!
And use a poublished version of cs_monero
2024-11-05 18:54:13 -06:00
julian
809a5a38e7 update cs_monero dep 2024-11-05 18:54:13 -06:00
julian
d3d6709763 use transactionV2 in xmr/wow wallets 2024-11-05 18:54:13 -06:00
julian
f0070b5aa8 hack in xmr and wow support to txV2 2024-11-05 18:54:13 -06:00
julian
11d1ceb40f changes and fixes to reflect cs_monero changes 2024-11-05 18:54:13 -06:00
Julian
699990883c fix some testnet related display bugs 2024-11-05 18:54:13 -06:00
Julian
e6b0733044 fix setting c_monero listeners 2024-11-05 18:54:13 -06:00
Julian
217bf9e301 update macos/ios templates 2024-11-05 18:54:13 -06:00
julian
07bf622fcd use main branch cs_monero 2024-11-05 18:54:13 -06:00
julian
bb2e8580e2 build scripts update 2024-11-05 18:54:13 -06:00
julian
b1eeddced1 more pubspec clean up 2024-11-05 18:54:13 -06:00
julian
c913b05fc9 fix a test 2024-11-05 18:54:13 -06:00
julian
16b9254761 WIP migrate flutter_libmonero to cs_monero 2024-11-05 18:54:13 -06:00
Diego Salazar
4109e7ed9f
Merge pull request from cypherstack/windows
Update secp256k1 build scripts IAW upstream and pin dependency
2024-10-23 14:23:31 -06:00
sneurlax
e2f3a1ad79 track secp256k1 changes in build scripts and pin to latest commit 2024-10-22 18:59:02 -05:00
sneurlax
b4610fb5b0 move 'rem's from native windows secp256k1 build script
and adjust path
2024-10-22 18:54:54 -05:00
julian
c13549472d update ref again 2024-10-02 12:54:35 -06:00
julian
75f3fe42c7 update refs 2024-10-02 08:52:17 -06:00
Diego Salazar
a04ea494a9
Merge pull request from cypherstack/firo-unstable-connection
unstable firo
2024-10-01 21:07:28 -06:00
julian
fec5f5883f dirty 2024-10-01 16:13:36 -06:00
julian
44fbab715a app config swap field defaults 2024-10-01 12:55:50 -06:00
julian
e0d2c8ec74 add some more logging and possible sync recovery fix? 2024-10-01 12:30:14 -06:00
julian
7d5cb72884 enable swap 2024-10-01 11:50:31 -06:00
julian
2c86520f37 libmonero submodule ref 2024-10-01 10:39:25 -06:00
julian
a779259b06 group testnet options on wallet creation screen 2024-10-01 10:39:25 -06:00
julian
29e63ca97d xmr/wow coin control 2024-10-01 10:39:25 -06:00
julian
7d60793c88 fix cw wallet listeners on restore 2024-10-01 10:39:25 -06:00
julian
642f0906b8 concurrent xmr/wow wallets 2024-10-01 10:39:25 -06:00
sneurlax
cdd9e078f8 update theme version in theme manifests 2024-09-30 13:18:29 -06:00
sneurlax
754f9b45fa fix cardano images and revert int value back to double 2024-09-30 12:06:01 -06:00
julian-CStack
4961908c28
Merge pull request from cypherstack/cardano
Add cbor package
2024-09-30 11:20:20 -06:00
sneurlax
05a5d18773 add cbor package
required by cardano via blockchain_utils (I think)
2024-09-25 18:16:51 -05:00
julian-CStack
2a605c012f
Merge pull request from cypherstack/cardano
update light and dark default themes for cardano
2024-09-25 13:38:02 -06:00
sneurlax
a3d3237e03 update light and dark default themes for cardano
resolve reversion in theme version &etc.
2024-09-25 14:12:50 -05:00
julian-CStack
4473e3d086
Merge pull request from cypherstack/cardano
add cardano themes
2024-09-23 10:50:35 -06:00
sneurlax
4a5cc3a968 Revert "update default campfire theme with cardano images and colors"
This reverts commit 8cc3737dea.
2024-09-23 11:46:06 -05:00
sneurlax
8cc3737dea update default campfire theme with cardano images and colors 2024-09-23 11:39:32 -05:00
sneurlax
f942ecd653 update default light and dark themes with cardano images and colors
i want to make a tool for this...
2024-09-23 11:39:04 -05:00
sneurlax
9a7ac9b615 add cardano 2024-09-22 22:36:07 -05:00
sneurlax
98d7ce3a8e Merge remote-tracking branch 'detherminal/staging' into cardano 2024-09-23 02:05:22 -05:00
Julian
3573f70004 bio fix 2024-09-20 17:07:55 -06:00
julian
412e3fdf07 Update frost and hide insecure addresses on receive page and in address list 2024-09-20 17:06:20 -06:00
Diego Salazar
94757f0f2e
Merge pull request from cypherstack/docs
Update docs to refer to flutter 3.24.3 (vs. 3.22.1), add Rust toolchain 1.71.0, mention secp256k1 scripts (if needed), change some ordering and grammar, etc.
2024-09-19 15:38:04 -06:00
sneurlax
53df0ecfb2
Merge branch 'staging' into docs 2024-09-19 13:11:12 -05:00
sneurlax
8e62c4257b
3.23.2->3.23.4 2024-09-19 13:09:39 -05:00
julian
1c73ac2635 fix bad submodule commit 2024-09-17 15:42:33 -06:00
julian
98986d74f0 update biometrics to handle updated local_auth changes 2024-09-17 15:06:56 -06:00
julian
f4b5060c8c strict proxy lib version 2024-09-17 15:06:56 -06:00
julian
8e5284854d fix android builds 2024-09-17 15:06:56 -06:00
julian
0cbc678b08 AGP even newer 2024-09-16 17:42:19 -06:00
julian
1740a42020 AGP compat updates 2024-09-16 16:34:04 -06:00
dethe
6cbc37f42c fix: post req body 2024-09-14 21:38:57 +03:00
dethe
e0051c8af2
Merge branch 'staging' into staging 2024-09-13 20:59:18 +03:00
sneurlax
57a50a96cd mirror mrcyjanek/monero_c to cypherstack as of 9/11 2024-09-11 11:42:34 -05:00
sneurlax
f7b367a3aa re-add vapigen to 20.04 docs 2024-09-11 11:32:07 -05:00
sneurlax
21334121c1
Merge branch 'staging' into docs 2024-09-11 00:26:56 -05:00
sneurlax
f6fe01f6d8 README updates
went through installation process and found multiple optimizations including better ordering and more complete notes in multiple places
2024-09-11 00:24:32 -05:00
sneurlax
9279295484 Merge remote-tracking branch 'origin/docs' into ubuntu-24.04 2024-09-11 00:20:02 -05:00
sneurlax
51c45d4332 touch docs and scripts
move windows dep from docs to script that's already ran according to the docs
but also correct the docs re: the windows scripts
2024-09-11 00:18:31 -05:00
sneurlax
99ea691bef update docs for 24.04 reqs 2024-09-10 23:51:23 -05:00
sneurlax
c47bf0b21c mirror flutter_libsparkmobile changes to cypherstack 2024-09-10 23:49:02 -05:00
sneurlax
2a2c42f23e
add 1.71.0 Rust toolchain to docs 2024-09-10 17:51:56 -05:00
sneurlax
233029ca21 add patch and git apply --stat scripts/dev/0001-ubuntu-24.04.patch
thanks, MrCyjaneK
2024-09-10 12:25:54 -05:00
Julian
b0128c867c fix built in system paste functionality (aka ctrl-p) on step two of desktop swap 2024-09-10 10:39:57 -06:00
sneurlax
b9b152a00e update docs to refer to flutter 3.24.2 (vs. 3.22.1) 2024-09-10 11:30:52 -05:00
julian
9ac0dd809e android fix 2024-09-06 11:49:25 -06:00
Julian
155395b977 Flutter 3.24.2 and dart 3.5.2 (fixes impeller issue on ios) 2024-09-06 11:49:25 -06:00
sneurlax
c34938a9be defer network calls from init to fetchChainHeight or serverCanBatch 2024-09-06 11:47:08 -06:00
sneurlax
0e0f9803cb do not allow taproot address as a simplex receiving address 2024-09-06 11:46:28 -06:00
sneurlax
87ca5b909d fix stackwallet-specific package import 2024-09-06 11:45:19 -06:00
julian
4b2d10b9b2 why is this suddenly needed? 2024-09-02 10:06:14 -06:00
dethe
1ec7ee95d2 feat: total tor support for cardano 2024-09-01 16:19:46 +03:00
dethe
02dc5c9416 refactor: show only lovelaces 2024-09-01 15:24:15 +03:00
dethe
e3d040b9b8 refactor: enhance ada txs 2024-09-01 15:12:09 +03:00
dethe
56dcc0ba4a
Merge branch 'cypherstack:staging' into staging 2024-09-01 14:49:46 +03:00
julian
8791003e33 fix android 2024-08-30 15:31:41 -06:00
Diego Salazar
db6486a688
Merge pull request from cypherstack/monero_c
Update monero_c to latest (3cb38bee)
2024-08-30 11:37:40 -06:00
sneurlax
6bb0279b67 update monero_c to latest (3cb38bee) 2024-08-30 12:37:04 -05:00
julian
4dc920772a handle assert nicely 2024-08-28 10:59:25 -06:00
julian
99e802b59e add ability to "send all" selected UTXOs when using coin control 2024-08-28 10:59:25 -06:00
julian
662bbd3099 token wallet state display bugfix on confirm send screen 2024-08-28 10:59:25 -06:00
sneurlax
2af6e32392
Merge branch 'staging' into staging 2024-08-28 11:47:05 -05:00
dethe
49ad183ff7 fix: add new packages used in cardano 2024-08-28 02:50:05 +03:00
dethe
5b324a0fc5 fix: remove special lib usage 2024-08-28 02:46:53 +03:00
julian
82d8acb7a2 erc20 gas limit 2024-08-27 17:08:26 -06:00
julian
0ddecd2f97 pre cache in wallet db sent eth and eth token txns on successful broadcast 2024-08-27 17:08:26 -06:00
julian
7da81d01ad pop back to token view after token send success on mobile 2024-08-27 17:08:26 -06:00
julian-CStack
dbc5fb7907
Merge pull request from cypherstack/uri
Filter unrecognized from extra URI parameters IAW BIP21
2024-08-27 17:06:11 -06:00
julian-CStack
2745598e9f
Merge branch 'staging' into uri 2024-08-27 17:06:02 -06:00
sneurlax
db5fcde918 fix _getCryptoCurrencyByScheme 2024-08-27 17:13:02 -05:00
sneurlax
19cae77e2b use AddressUtils where appropriate
instead of duplicating logic
2024-08-27 16:55:19 -05:00
sneurlax
b73628d939 update uri parsing code to support monero URIs
bitcoin URIs now also validate properly
2024-08-27 16:41:30 -05:00
julian-CStack
319080cbca
Merge pull request from cypherstack/deskcam
Add desktop webcam to FROST process
2024-08-27 15:36:32 -06:00
sneurlax
dd11214b3c Merge branch 'staging' into uri 2024-08-27 13:09:50 -05:00
sneurlax
66f29ab1f5 Merge branch 'staging' into deskcam 2024-08-27 13:07:39 -05:00
julian-CStack
be324a6332
Merge pull request from cypherstack/monero_c
Update monero_c to latest and Monero to 0.18.3.4
2024-08-27 09:09:41 -06:00
sneurlax
d21225adfc bump monero_c to 294b593d and monero to 0.18.3.4 2024-08-27 10:08:49 -05:00
dethe
27d319cece feat: add cardano 2024-08-26 20:38:58 +03:00
sneurlax
20ec9edf56 update monero_c to latest and Monero to 0.18.3.4
TODO update to refer to flutter_libmonero#main after our https://github.com/cypherstack/flutter_libmonero/pull/73 is merged (and their monero_c#38 is merged to their #master)
2024-08-23 16:35:50 -05:00
sneurlax
d78050ee79 remove now-unneeded monero_c wownero imports 2024-08-15 19:38:29 -05:00
sneurlax
6723614712 add missing imports 2024-08-13 15:52:50 -05:00
sneurlax
e383c6202a fix cw wallet restores from backup 2024-08-10 22:46:09 -05:00
sneurlax
7446a56631 simplify test logic 2024-08-08 16:37:44 -05:00
sneurlax
2907f7d962 silence print 2024-08-08 14:55:53 -05:00
sneurlax
ce74f9508b replace dialog with flushbar message 2024-08-05 16:28:45 -05:00
sneurlax
16a2b23dde refactor QrCodeScannerDialog into its own widget, use thru Frost process 2024-08-02 14:40:38 -05:00
sneurlax
2145334152 remove onSnackbarMessage, do not show error on regular scans, only files 2024-07-31 16:43:15 -06:00
julian
810f8bb3c5 handle deleted wallets cleanly in the overview list 2024-07-31 16:31:57 -06:00
julian
d6c609fea4 ask before enabling toggle 2024-07-31 16:31:57 -06:00
sneurlax
237eb5cd8e fix monero onion node test 2024-07-31 14:35:10 -06:00
sneurlax
c2d6b84129 julian's patch
love it
2024-07-31 14:35:10 -06:00
julian
031bfca492 update lelantus lib 2024-07-31 10:51:51 -06:00
sneurlax
11d85231cc add opencv package (camera_linux dependency) to building docs 2024-07-31 10:51:04 -06:00
sneurlax
db87beef90 convert snackbar messages to dialog messages
remove unused CameraLinux instance
refactor delay to be more easily edited (at the cost of not being const any more)
2024-07-30 18:09:17 -06:00
sneurlax
cd38a5153b initialize camera on macos
and quiet warning re: NSCameraUseContinuityCameraDeviceType
2024-07-30 18:09:17 -06:00
sneurlax
c708ace18c autogenerated macos deskcam changes 2024-07-30 18:09:17 -06:00
sneurlax
1d49cc83e9 use camera_macos package on macos for qr code scanning 2024-07-30 18:09:17 -06:00
sneurlax
f2b1653ea4 add macos camera permission
TODO remove audio permission, currently required by plugin.  see https://pub.dev/packages/camera_macos#setup
2024-07-30 18:09:17 -06:00
sneurlax
c8bc9eded5 add camera_macos package 2024-07-30 18:09:17 -06:00
sneurlax
84108eb6ba comments notes and tweaks 2024-07-30 18:09:17 -06:00
sneurlax
be3c02ed2a make ui less janky 2024-07-30 18:09:17 -06:00
sneurlax
6fa56bfe6d use camera_windows fork for windows webcam support
I wish I could use the CameraPlatformInterface in a platform-agnostic way

windows desktop webcam scan fixes

and log cleanup
2024-07-30 18:09:17 -06:00
sneurlax
63ee105aea flutter pub add cypherstack/packages/.../packages/camera/camera_windows 2024-07-30 18:09:17 -06:00
sneurlax
7477922382 add file selection button
still janky, it should show snackbar messages on errors but doesn't. ffs
2024-07-30 18:09:17 -06:00
sneurlax
8bf8a90404 "live" webcam image in qr code dialog
still a little janky... add debug prints thru the process to see what I mean
but it works, so...
2024-07-30 18:09:17 -06:00
sneurlax
04ce0f89fc use zxing2 to decode, display image in dialog for troubleshooting
flutter pub add zxing2
etc

fix image display in poc
2024-07-30 18:09:17 -06:00
sneurlax
f5ca4ffdd0 poc of getting an image from webcam
but doesn't work as pushed, need to parse image correctly
2024-07-30 18:09:17 -06:00
sneurlax
32380c3ac1 flutter pub add camera_linux 2024-07-30 18:09:17 -06:00
sneurlax
d68e416a74 correct node testing logic 2024-07-30 18:08:21 -06:00
sneurlax
ecf56b21c0 add onion-specific test cases
cannot test onion node without proxyInfo and no need to test https for onion node
2024-07-30 18:08:21 -06:00
sneurlax
23c76b5034 add proxyInfo-aware timeout to node test 2024-07-30 18:08:21 -06:00
sneurlax
1153162fa9 change node test logic to support onion and proxied nodes properly 2024-07-30 18:08:21 -06:00
sneurlax
b6dd28562b partial reversion of previous commit 2024-07-30 18:08:21 -06:00
sneurlax
615fdfb5bf monero onion node test patch
might need more work to prevent the changes throughout the stack ... would be good to limit it to 1 or 2 changes instead of 3

also added proxyInfo-contextual timeout
2024-07-30 18:08:21 -06:00
julian
4d1fde7671 prepare send failure logging 2024-07-30 08:43:25 -06:00
julian-CStack
b1a303ffdc
Merge pull request from cypherstack/togglebalance
Quick toggle balances as appropriate
2024-07-29 12:16:09 -06:00
julian
90aae703aa mobile balance toggle update 2024-07-29 12:15:06 -06:00
julian-CStack
e91daa943a
Merge branch 'staging' into togglebalance 2024-07-29 11:18:57 -06:00
julian-CStack
9ab411bcb9
Merge pull request from cypherstack/hideex
Disable Swap and Buy crypto features based on user preference
2024-07-29 11:10:42 -06:00
julian
7e12ec604c desktop menu toggle state fix 2024-07-29 11:09:13 -06:00
julian-CStack
08d3e0abb5
Merge branch 'staging' into hideex 2024-07-29 10:37:36 -06:00
julian
751adb50bd update assets 2024-07-24 12:56:22 -06:00
julian
ce1b1f0ffb just exit(0); on desktop because why not... 2024-07-22 17:12:59 -06:00
julian
c6836708a8 Hook up missing spark fee estimate call.
Should address https://github.com/cypherstack/stack_wallet/issues/948
2024-07-22 17:12:59 -06:00
Julian
3b38dd6464 Add scrollable for desktop. Addresses https://github.com/cypherstack/stack_wallet/issues/949 2024-07-22 17:12:59 -06:00
Julian
2d06a23c97 Don't hold up app loading while waiting for permissions from user on macos. Addresses https://github.com/cypherstack/stack_wallet/issues/936 2024-07-22 17:12:59 -06:00
julian
4f5354da0d No reason to show a selection dialog or even show which coin if its implied in a single coin config.
Addresses https://github.com/cypherstack/stack_wallet/issues/947
2024-07-22 17:12:59 -06:00
julian
f3d1611249 fixes: https://github.com/cypherstack/stack_wallet/issues/908 2024-07-22 17:12:59 -06:00
julian
0ed6f2689a send from xmr/wow disabled due to concurrent libmonero based wallets restriction 2024-07-22 12:40:04 -06:00
julian
7ccb403ed3 add fuzzy check to handle some api endpoints that think consistency doesn't matter 2024-07-22 12:40:04 -06:00
julian
a4a7abd6b8 look ahead on frost wallet addresses to check for transactions on future addresses 2024-07-18 08:43:49 -06:00
julian
6a9c58d012 fix bug I introduced last commit 2024-07-17 15:46:04 -06:00
julian
d546d5de97 bad missing funds error fix 2024-07-17 10:53:28 -06:00
julian
7c3703ffd7 frost multi address functionality 2024-07-17 10:19:39 -06:00
julian
367daad3c5 ui bugfixes 2024-07-17 10:19:39 -06:00
Julian
6f4493f638 update generated 2024-07-17 08:41:28 -06:00
Julian
5c7983154a sent to address isar model schema 2024-07-17 08:41:28 -06:00
sneurlax
91037cc5a6 patch swb directory selection on windows
had paths with mixed usage of / and \

closes https://github.com/cypherstack/stack_wallet/issues/829
2024-07-16 12:34:07 -06:00
sneurlax
d1780aa82e remove "by default" from "Reuse receiving address" string 2024-07-16 12:33:01 -06:00
sneurlax
5d2ec00407 spacing fix 2024-07-16 12:33:01 -06:00
sneurlax
21b7bfcb4e check if pasted value is URI 2024-07-16 10:46:22 -05:00
sneurlax
1ff17d8b0c Merge branch 'staging' into uri 2024-07-16 10:24:07 -05:00
julian
50bd3e52a3 prevent submit button activation when autopin is on and being checked and do not fetch pin from sec store unless min pin length met 2024-07-15 16:50:00 -06:00
julian
816eb37477 show n/x confirms while unconfirmed 2024-07-15 15:21:03 -06:00
julian
4acfbde791 show n confirmations on tx details screen 2024-07-15 15:21:03 -06:00
julian
80d6a1bed7 fixes https://github.com/cypherstack/stack_wallet/issues/795 2024-07-15 14:26:31 -06:00
julian-CStack
86f6a3cd64
Merge pull request from cypherstack/epic_fixes
Epic fixes
2024-07-15 14:13:48 -06:00
sneurlax
c38a7c0adb update flutter_libepiccash ref
to #main

also epic-wallet (to #master)
2024-07-15 14:49:32 -05:00
sneurlax
f1b46adfaf remove SYSTEM_ALERT_WINDOW perm 2024-07-15 13:31:46 -05:00
sneurlax
a52f53e116 add and use epic-wallet submodule 2024-07-15 12:17:32 -05:00
sneurlax
133bcb231d use local epic-wallet in flutter_libepiccash for troubleshooting 2024-07-12 18:24:13 -05:00
julian
754c6e6440 null error fix on send from stack when doing epic to any swap 2024-07-12 11:28:04 -06:00
sneurlax
3a9e7d700b filter unrecognized from extra URI parameters IAW BIP21
Closes  https://github.com/cypherstack/stack_wallet/issues/567

TODO refer to BIP21 to see if any other params are required
2024-07-11 18:57:25 -05:00
julian-CStack
c5a14815ec
Merge pull request from cypherstack/testing
tweaks
2024-07-11 11:18:38 -06:00
julian
2da9c9ef85 clean up wallets list on desktop and add keys to widgets in list 2024-07-11 10:41:59 -06:00
julian
3a1b86f02d ignore verification of passphrase if passphrase is empty... 2024-07-11 09:58:50 -06:00
Diego Salazar
9c37f99e9e
Merge pull request from cypherstack/staging
Update to 2.1.2
2024-07-10 15:05:49 -06:00
sneurlax
a066f77639 fix attempt to toggle enableExchange while desktop menu minimized 2024-07-05 14:46:14 -05:00
sneurlax
38defea3d1 Merge remote-tracking branch 'origin/staging' into hideex 2024-07-05 14:37:22 -05:00
sneurlax
b3e5f31e7e refactor _getShowExchange -> _getEnableExchange
to be more semantically consistent
2024-07-04 15:24:23 -05:00
sneurlax
c64cde30a7 Merge remote-tracking branch 'origin/staging' into hideex 2024-07-04 15:23:17 -05:00
sneurlax
f8e8578323 Merge remote-tracking branch 'origin/staging' into togglebalance 2024-07-04 15:21:37 -05:00
julian
314c68fcea fix showing wallet button when no other options exist on mobile home screen 2024-07-04 10:13:11 -06:00
julian
0a822e8e22 fix missing pref init 2024-07-04 09:54:22 -06:00
sneurlax
9e6d9f8bad
Merge branch 'staging' into togglebalance 2024-07-03 17:46:55 -05:00
sneurlax
220cf65520 disable exchange data loading based on enableExchange pref
and refactor showExchange->enableExchange
2024-07-02 22:52:51 -05:00
sneurlax
2b2127aeb5 hide swap and buy buttons around the ui
and const keys
2024-07-02 22:41:00 -05:00
sneurlax
1e9775eded add unique keys to each button so they aren't reused
flutter would reuse widgets which would cause weird behavior like removing "Support" and "About" instead of "Swap" and "Buy crypto", and/or adding additional "Support" and "About" items upon hot reload
2024-07-02 22:23:47 -05:00
sneurlax
a080e65ee5 hide exchange menu items contextually
WHY doesn't this work tho?
2024-07-02 19:09:07 -05:00
sneurlax
9b692f9703 add showexchange pref to advanced settings 2024-07-02 17:01:36 -05:00
sneurlax
bc1a0dc586 add showExchange pref 2024-07-02 16:30:19 -05:00
sneurlax
8faac03954 count pending balances as valid 2024-07-02 11:49:44 -05:00
sneurlax
a69cc80e61 only affect firo wallets 2024-07-02 11:49:40 -05:00
sneurlax
005fcdf44f hide down chevron contextually 2024-07-02 11:14:23 -05:00
sneurlax
a2308d3e78 quick toggle balances as appropriate
if only 2 balances exist, toggle them instead of showing the dialog.
2024-06-30 22:08:25 -05:00
Diego Salazar
cec219f3f9
Merge pull request from cypherstack/staging
Update to version 2.1.1
2024-06-29 11:34:37 -06:00
Diego Salazar
f5489feae7
Merge pull request from cypherstack/staging
Update to version 2.0.0
2024-05-14 11:03:42 -06:00
545 changed files with 36252 additions and 13432 deletions
.gitignore.gitmodules
android
asset_sources
default_themes
campfire
stack_duo
stack_wallet
svg
campfire
stack_duo
stack_wallet
assets/gif
crypto_plugins
docs
fastlane
ios
MoneroWallet.framework
Podfile.lock
Runner.xcodeproj/xcshareddata/xcschemes
Runner
WowneroWallet.framework
lib

33
.gitignore vendored
View file

@ -20,6 +20,9 @@
# is commented out by default.
#.vscode/
#CppWinRT manual install
Microsoft.Windows*
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
@ -29,6 +32,7 @@
.pub-cache/
.pub/
/build/
android/app/.cxx
# Web related
lib/generated_plugin_registrant.dart
@ -58,8 +62,6 @@ coverage
scripts/**/build
/lib/external_api_keys.dart
libcw_monero.dll
libcw_wownero.dll
libepic_cash_wallet.dll
libmobileliblelantus.dll
libtor_ffi.dll
@ -69,6 +71,10 @@ secp256k1.dll
/lib/app_config.g.dart
/android/app/src/main/app_icon-playstore.png
# Dart generated files (Freezed, Riverpod, GoRouter etc..)
lib/**/*.g.dart
lib/**/*.freezed.dart
## other generated project files
pubspec.yaml
@ -101,21 +107,8 @@ pubspec.yaml
# FVM Version Cache
.fvm/
android/app/src/main/jniLibs/arm64-v8a/libwownero_wallet2_api_c.so
android/app/src/main/jniLibs/arm64-v8a/libmonero_wallet2_api_c.so
android/app/src/main/jniLibs/armeabi-v7a/libmonero_wallet2_api_c.so
android/app/src/main/jniLibs/armeabi-v7a/libwownero_wallet2_api_c.so
android/app/src/main/jniLibs/x86_64/libmonero_wallet2_api_c.so
android/app/src/main/jniLibs/x86_64/libwownero_wallet2_api_c.so
macos/monero_wallet2_api_c.dylib
macos/wownero_wallet2_api_c.dylib
/macos/monero_libwallet2_api_c.dylib
/macos/wownero_libwallet2_api_c.dylib
/ios/monero_libwallet2_api_c.dylib
/ios/wownero_libwallet2_api_c.dylib
/android/app/src/main/jniLibs/arm64-v8a/libmonero_libwallet2_api_c.so
/android/app/src/main/jniLibs/armeabi-v7a/libmonero_libwallet2_api_c.so
/android/app/src/main/jniLibs/x86_64/libmonero_libwallet2_api_c.so
/android/app/src/main/jniLibs/arm64-v8a/libwownero_libwallet2_api_c.so
/android/app/src/main/jniLibs/armeabi-v7a/libwownero_libwallet2_api_c.so
/android/app/src/main/jniLibs/x86_64/libwownero_libwallet2_api_c.so
scripts/linux/build/libsecret/subprojects/gi-docgen/.meson-subproject-wrap-hash.txt
crypto_plugins/cs_monero/built_outputs
crypto_plugins/cs_monero/build
crypto_plugins/*.diff

3
.gitmodules vendored
View file

@ -1,9 +1,6 @@
[submodule "crypto_plugins/flutter_libepiccash"]
path = crypto_plugins/flutter_libepiccash
url = https://github.com/cypherstack/flutter_libepiccash.git
[submodule "crypto_plugins/flutter_libmonero"]
path = crypto_plugins/flutter_libmonero
url = https://github.com/cypherstack/flutter_libmonero.git
[submodule "crypto_plugins/flutter_liblelantus"]
path = crypto_plugins/flutter_liblelantus
url = https://github.com/cypherstack/flutter_liblelantus.git

View file

@ -1,16 +1,3 @@
buildscript {
ext.kotlin_version = '1.8.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
@ -18,12 +5,12 @@ allprojects {
}
}
rootProject.buildDir = '../build'
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {

View file

@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
android.enableJetifier=true

View file

@ -1,6 +1,5 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip

View file

@ -1,11 +1,25 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version '8.7.0' apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}
include ":app"

View file

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.77444 13.4823C9.60687 13.4092 9.43072 13.3749 9.25027 13.3749H3.75081C2.99076 13.3749 2.37594 13.9897 2.37594 14.7497C2.37594 15.5098 2.99076 16.1246 3.75081 16.1246H5.93126L1.40279 20.6531C0.865736 21.1901 0.865736 22.0602 1.40279 22.5972C1.93985 23.1343 2.80988 23.1343 3.34694 22.5972L7.8754 18.0709V20.2492C7.8754 21.0092 8.49023 21.6241 9.25027 21.6241C10.0103 21.6241 10.6251 21.0092 10.6251 20.2492V14.7497C10.6251 14.5708 10.5887 14.3926 10.5192 14.2247C10.3802 13.8861 10.1139 13.6198 9.77444 13.4823ZM14.2256 10.5177C14.3931 10.5908 14.5693 10.6251 14.7497 10.6251H20.2492C21.0092 10.6251 21.6241 10.0103 21.6241 9.25027C21.6241 8.49023 21.0092 7.8754 20.2492 7.8754H18.0687L22.5972 3.34694C23.1343 2.80988 23.1343 1.93985 22.5972 1.40279C22.0606 0.866166 21.1905 0.865306 20.6531 1.40279L16.1246 5.93341V3.75081C16.1246 2.99076 15.5098 2.37594 14.7497 2.37594C13.9897 2.37594 13.3749 2.99076 13.3749 3.75081V9.25027C13.3749 9.42917 13.4113 9.60739 13.4807 9.7753C13.6198 10.1139 13.8861 10.3802 14.2256 10.5177ZM9.25027 2.37594C8.4898 2.37594 7.8754 2.99076 7.8754 3.75081V5.93126L3.34823 1.40387C2.81117 0.86681 1.94114 0.86681 1.40408 1.40387C0.867025 1.94092 0.867025 2.81096 1.40408 3.34801L5.93341 7.8754H3.75081C2.99076 7.8754 2.37594 8.4898 2.37594 9.25027C2.37594 10.0107 2.99076 10.6251 3.75081 10.6251H9.25027C9.42917 10.6251 9.60739 10.5887 9.7753 10.5192C10.1139 10.3802 10.3802 10.1139 10.5177 9.77444C10.5908 9.60687 10.6251 9.43072 10.6251 9.25027V3.75081C10.6251 2.99076 10.0107 2.37594 9.25027 2.37594ZM18.0709 16.1246H20.2492C21.0092 16.1246 21.6241 15.5098 21.6241 14.7497C21.6241 13.9897 21.0092 13.3749 20.2492 13.3749H14.7497C14.5708 13.3749 14.3926 13.4113 14.2247 13.4806C13.8879 13.6199 13.6198 13.8879 13.4806 14.2247C13.4092 14.3931 13.3749 14.5693 13.3749 14.7497V20.2492C13.3749 21.0092 13.9897 21.6241 14.7497 21.6241C15.5098 21.6241 16.1246 21.0092 16.1246 20.2492V18.0687L20.6531 22.5972C21.1901 23.1343 22.0602 23.1343 22.5972 22.5972C23.1338 22.0606 23.1347 21.1905 22.5972 20.6531L18.0709 16.1246Z" fill="black"/>
</svg>

After

(image error) Size: 2.1 KiB

View file

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.77444 13.4823C9.60687 13.4092 9.43072 13.3749 9.25027 13.3749H3.75081C2.99076 13.3749 2.37594 13.9897 2.37594 14.7497C2.37594 15.5098 2.99076 16.1246 3.75081 16.1246H5.93126L1.40279 20.6531C0.865736 21.1901 0.865736 22.0602 1.40279 22.5972C1.93985 23.1343 2.80988 23.1343 3.34694 22.5972L7.8754 18.0709V20.2492C7.8754 21.0092 8.49023 21.6241 9.25027 21.6241C10.0103 21.6241 10.6251 21.0092 10.6251 20.2492V14.7497C10.6251 14.5708 10.5887 14.3926 10.5192 14.2247C10.3802 13.8861 10.1139 13.6198 9.77444 13.4823ZM14.2256 10.5177C14.3931 10.5908 14.5693 10.6251 14.7497 10.6251H20.2492C21.0092 10.6251 21.6241 10.0103 21.6241 9.25027C21.6241 8.49023 21.0092 7.8754 20.2492 7.8754H18.0687L22.5972 3.34694C23.1343 2.80988 23.1343 1.93985 22.5972 1.40279C22.0606 0.866166 21.1905 0.865306 20.6531 1.40279L16.1246 5.93341V3.75081C16.1246 2.99076 15.5098 2.37594 14.7497 2.37594C13.9897 2.37594 13.3749 2.99076 13.3749 3.75081V9.25027C13.3749 9.42917 13.4113 9.60739 13.4807 9.7753C13.6198 10.1139 13.8861 10.3802 14.2256 10.5177ZM9.25027 2.37594C8.4898 2.37594 7.8754 2.99076 7.8754 3.75081V5.93126L3.34823 1.40387C2.81117 0.86681 1.94114 0.86681 1.40408 1.40387C0.867025 1.94092 0.867025 2.81096 1.40408 3.34801L5.93341 7.8754H3.75081C2.99076 7.8754 2.37594 8.4898 2.37594 9.25027C2.37594 10.0107 2.99076 10.6251 3.75081 10.6251H9.25027C9.42917 10.6251 9.60739 10.5887 9.7753 10.5192C10.1139 10.3802 10.3802 10.1139 10.5177 9.77444C10.5908 9.60687 10.6251 9.43072 10.6251 9.25027V3.75081C10.6251 2.99076 10.0107 2.37594 9.25027 2.37594ZM18.0709 16.1246H20.2492C21.0092 16.1246 21.6241 15.5098 21.6241 14.7497C21.6241 13.9897 21.0092 13.3749 20.2492 13.3749H14.7497C14.5708 13.3749 14.3926 13.4113 14.2247 13.4806C13.8879 13.6199 13.6198 13.8879 13.4806 14.2247C13.4092 14.3931 13.3749 14.5693 13.3749 14.7497V20.2492C13.3749 21.0092 13.9897 21.6241 14.7497 21.6241C15.5098 21.6241 16.1246 21.0092 16.1246 20.2492V18.0687L20.6531 22.5972C21.1901 23.1343 22.0602 23.1343 22.5972 22.5972C23.1338 22.0606 23.1347 21.1905 22.5972 20.6531L18.0709 16.1246Z" fill="black"/>
</svg>

After

(image error) Size: 2.1 KiB

View file

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.77444 13.4823C9.60687 13.4092 9.43072 13.3749 9.25027 13.3749H3.75081C2.99076 13.3749 2.37594 13.9897 2.37594 14.7497C2.37594 15.5098 2.99076 16.1246 3.75081 16.1246H5.93126L1.40279 20.6531C0.865736 21.1901 0.865736 22.0602 1.40279 22.5972C1.93985 23.1343 2.80988 23.1343 3.34694 22.5972L7.8754 18.0709V20.2492C7.8754 21.0092 8.49023 21.6241 9.25027 21.6241C10.0103 21.6241 10.6251 21.0092 10.6251 20.2492V14.7497C10.6251 14.5708 10.5887 14.3926 10.5192 14.2247C10.3802 13.8861 10.1139 13.6198 9.77444 13.4823ZM14.2256 10.5177C14.3931 10.5908 14.5693 10.6251 14.7497 10.6251H20.2492C21.0092 10.6251 21.6241 10.0103 21.6241 9.25027C21.6241 8.49023 21.0092 7.8754 20.2492 7.8754H18.0687L22.5972 3.34694C23.1343 2.80988 23.1343 1.93985 22.5972 1.40279C22.0606 0.866166 21.1905 0.865306 20.6531 1.40279L16.1246 5.93341V3.75081C16.1246 2.99076 15.5098 2.37594 14.7497 2.37594C13.9897 2.37594 13.3749 2.99076 13.3749 3.75081V9.25027C13.3749 9.42917 13.4113 9.60739 13.4807 9.7753C13.6198 10.1139 13.8861 10.3802 14.2256 10.5177ZM9.25027 2.37594C8.4898 2.37594 7.8754 2.99076 7.8754 3.75081V5.93126L3.34823 1.40387C2.81117 0.86681 1.94114 0.86681 1.40408 1.40387C0.867025 1.94092 0.867025 2.81096 1.40408 3.34801L5.93341 7.8754H3.75081C2.99076 7.8754 2.37594 8.4898 2.37594 9.25027C2.37594 10.0107 2.99076 10.6251 3.75081 10.6251H9.25027C9.42917 10.6251 9.60739 10.5887 9.7753 10.5192C10.1139 10.3802 10.3802 10.1139 10.5177 9.77444C10.5908 9.60687 10.6251 9.43072 10.6251 9.25027V3.75081C10.6251 2.99076 10.0107 2.37594 9.25027 2.37594ZM18.0709 16.1246H20.2492C21.0092 16.1246 21.6241 15.5098 21.6241 14.7497C21.6241 13.9897 21.0092 13.3749 20.2492 13.3749H14.7497C14.5708 13.3749 14.3926 13.4113 14.2247 13.4806C13.8879 13.6199 13.6198 13.8879 13.4806 14.2247C13.4092 14.3931 13.3749 14.5693 13.3749 14.7497V20.2492C13.3749 21.0092 13.9897 21.6241 14.7497 21.6241C15.5098 21.6241 16.1246 21.0092 16.1246 20.2492V18.0687L20.6531 22.5972C21.1901 23.1343 22.0602 23.1343 22.5972 22.5972C23.1338 22.0606 23.1347 21.1905 22.5972 20.6531L18.0709 16.1246Z" fill="black"/>
</svg>

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 2.2 MiB

@ -1 +1 @@
Subproject commit 19c76409e55f1bfed58855eb767574604376edb6
Subproject commit 25e6cb3a3e7bee04e425af6beccb47e8d0708fdb

@ -1 +1 @@
Subproject commit b654bf4488357c8a104900e11f9468d54a39f22b
Subproject commit 7b325030bce46a423aa46497d1a608b7a8a58976

@ -1 +0,0 @@
Subproject commit 982f5ab19fe0dd3dd3f6be2c46f8dff13d49027c

@ -1 +1 @@
Subproject commit d539de2348bdbb87bac341dcaa6a0755f21d48e2
Subproject commit 6f1310eccd336fb3c8dc00b61e39a3f0f3a2b59a

View file

@ -13,12 +13,12 @@ Here you will find instructions on how to install the necessary tools for buildi
The following instructions are for building and running on a Linux host. Alternatively, see the [Mac](#mac-host) and/or [Windows](#windows-host) section. This entire section (except for the Android Studio section) needs to be completed in WSL if building on a Windows host.
### Flutter
Install Flutter 3.22.1 by [following their guide](https://docs.flutter.dev/get-started/install/linux/desktop?tab=download#install-the-flutter-sdk). You can also clone https://github.com/flutter/flutter, check out the `3.22.1` tag, and add its `flutter/bin` folder to your PATH as in
Install Flutter 3.29.2 by [following their guide](https://docs.flutter.dev/get-started/install/linux/desktop?tab=download#install-the-flutter-sdk). You can also clone https://github.com/flutter/flutter, check out the `3.29.2` tag, and add its `flutter/bin` folder to your PATH as in
```sh
FLUTTER_DIR="$HOME/development/flutter"
git clone https://github.com/flutter/flutter.git "$FLUTTER_DIR"
cd "$FLUTTER_DIR"
git checkout 3.22.1
git checkout 3.29.2
echo 'export PATH="$PATH:'"$FLUTTER_DIR"'/bin"' >> "$HOME/.profile"
source "$HOME/.profile"
flutter precache
@ -38,7 +38,7 @@ Use `Tools > SDK Manager` to install:
- `SDK Tools > Android SDK command line tools`
- `SDK Tools > CMake`
and for Android builds,
- `SDK Tools > Android SDK (API 30)`
- `SDK Tools > Android SDK (API 35)`
- `SDK Tools > NDK`
Then in `File > Settings > Plugins`, install the **Flutter** and **Dart** plugins and restart the IDE. In `File > Settings > Languages & Frameworks > Flutter > Editor`, enable auto format on save to match the project's code style. If you have problems with the Dart SDK, make sure to run `flutter` in a terminal to download it (use `source ~/.bashrc` to update your environment variables if you're still using the same terminal from which you ran `setup.sh`). Run `flutter doctor` to install any missing dependencies and review and agree to any license agreements.
@ -53,16 +53,28 @@ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-
### Build dependencies
Install basic dependencies
```
sudo apt-get install libssl-dev curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake libgit2-dev clang libncurses5-dev libncursesw5-dev zlib1g-dev llvm python3-distutils g++ gcc gperf
sudo apt-get install libssl-dev curl unzip automake build-essential file pkg-config git python3 libtool libtinfo6 cmake libgit2-dev clang libncurses5-dev libncursesw5-dev zlib1g-dev llvm g++ gcc gperf libopencv-dev python3-typogrify xsltproc valac gobject-introspection meson
```
Install [Rust](https://www.rust-lang.org/tools/install) with command:
For Ubuntu 20.04,
```
sudo apt-get install valac
pip3 install --upgrade meson==0.64.1 markdown==3.4.1 markupsafe==2.1.1 jinja2==3.1.2 pygments==2.13.0 toml==0.10.2 typogrify==2.0.7 tomli==2.0.1
```
For Ubuntu 24.04,
```
sudo apt install pipx libgcrypt20-dev libglib2.0-dev libsecret-1-dev
pipx install meson==0.64.1 markdown==3.4.1 markupsafe==2.1.1 jinja2==3.1.2 pygments==2.13.0 toml==0.10.2 typogrify==2.0.7 tomli==2.0.1
```
Install [Rust](https://www.rust-lang.org/tools/install) via [rustup.rs](https://rustup.rs), the required Rust toolchains, and `cargo-ndk` with command:
```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.bashrc
rustup install 1.67.1 1.72.0 1.73.0
rustup default 1.67.1
cargo install cargo-ndk --version 2.12.7 --locked
source ~/.bashrc
rustup install 1.85.1 1.81.0
rustup default 1.85.1
cargo install cargo-ndk
```
Android specific dependencies:
@ -77,6 +89,7 @@ sudo apt-get install clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev
pip3 install --upgrade meson==0.64.1 markdown==3.4.1 markupsafe==2.1.1 jinja2==3.1.2 pygments==2.13.0 toml==0.10.2 typogrify==2.0.7 tomli==2.0.1
```
### Clone the repository and initialize submodules
After installing the prerequisites listed above, download the code and init the submodules
```
git clone https://github.com/cypherstack/stack_wallet.git
@ -92,17 +105,15 @@ cd scripts/linux
cd ../..
```
### Build coinlib
Coinlib's native secp256k1 library must be built prior to running Stack Wallet. It can be built from within the root `stack_wallet` folder on a...
- Linux host for Linux targets: `dart run coinlib:build_linux`, or
### Build secp256k1
Coinlib requires a secp256k1 library to be built prior to running Stack Wallet. It can be built from within the root `stack_wallet` folder on a...
- Linux host for Linux targets: `dart run coinlib:build_linux` (requires [Docker](https://docs.docker.com/engine/install/ubuntu/) or [`podman`](https://podman.io/docs/installation))
- Linux host for Windows targets: `dart run coinlib:build_windows_crosscompile`
- Windows host: `dart run coinlib:build_windows`
- WSL2 host: `dart run coinlib:build_wsl`
- macOS host: `dart run coinlib:build_macos`
To build coinlib on Linux, you will need `docker` (see [installation instructions](https://docs.docker.com/engine/install/ubuntu/)) or [`podman`](https://podman.io/docs/installation) (`sudo apt-get -y install podman`)
For Windows targets, you can use a `secp256k1.dll` produced by any of the three middle options if the first attempt doesn't succeed.
or by using `scripts/linux/build_secp256k1.sh` or `scripts/windows/build_secp256k1.bat`.
### Run prebuild script
@ -117,7 +128,7 @@ or manually by creating the files referenced in that script with the specified c
### Build plugins
#### Build script: `build_app.sh`
The `build_app.sh` script is use to build applications Stack Wallet. View the script's help message with `./build_app.sh -h` for more information on its usage.
The `build_app.sh` script is used to build the Stack Wallet and its family of applications. View the script's help message with `./build_app.sh -h` for more information on its usage.
Options:
@ -145,24 +156,17 @@ cd scripts
./build_app.sh -a stack_wallet -p linux
```
##### Remove system packages (may be needed for building flutter_libmonero)
[`flutter_libmonero`](https://github.com/cypherstack/flutter_libmonero) may have issues building due to conflicts with system packages: if so, follow this section.
Remove pre-installed system libraries for the following packages built by cryptography plugins in the crypto_plugins folder: `boost iconv libjson-dev libsecret openssl sodium unbound zmq`. You can use
```
sudo apt list --installed | grep boost
```
for example to find which pre-installed packages you may need to remove with `sudo apt remove`. Be careful, as some packages (especially boost) are linked to GNOME (GUI) packages: when in doubt, remove `-dev` packages first like with
```
sudo apt-get remove '^libboost.*-dev.*'
```
<!-- TODO: configure compiler to prefer built over system libraries. Should already use them? -->
#### Building plugins and configure for Windows
Install dependencies like MXE:
```
cd scripts
cd scripts/windows
./deps.sh
./build_app.sh -a stack_wallet -p windows
```
and use `scripts/build_app.sh` to build plugins:
```
cd ..
./build_app.sh -a stack_wallet -p windows -v 2.1.0 -b 210
```
### Running
@ -205,13 +209,13 @@ brew install brotli cairo coreutils gdbm gettext glib gmp libevent libidn2 libng
```
<!-- TODO: determine which of the above list are not needed at all. -->
Download and install [Rust](https://www.rust-lang.org/tools/install). [Rustup](https://rustup.rs/) is recommended for Rust setup. Use `rustc` to confirm successful installation. Install toolchains 1.67.1 and 1.72.0 and `cbindgen` and `cargo-lipo` too. You will also have to add the platform target(s) `aarch64-apple-ios` and/or `aarch64-apple-darwin`. You can use the command(s):
Download and install [Rust](https://www.rust-lang.org/tools/install). [Rustup](https://rustup.rs/) is recommended for Rust setup. Use `rustc` to confirm successful installation. Install toolchains 1.81.0 and 1.85.1 and `cbindgen` and `cargo-lipo` too. You will also have to add the platform target(s) `aarch64-apple-ios` and/or `aarch64-apple-darwin`. You can use the command(s):
```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.bashrc
rustup install 1.67.1 1.72.0 1.73.0
rustup default 1.67.1
cargo install cargo-ndk --version 2.12.7 --locked
rustup install 1.85.1 1.81.0
rustup default 1.85.1
cargo install cargo-ndk
cargo install cbindgen cargo-lipo
rustup target add aarch64-apple-ios aarch64-apple-darwin
```
@ -219,7 +223,7 @@ rustup target add aarch64-apple-ios aarch64-apple-darwin
Optionally download [Android Studio](https://developer.android.com/studio) as an IDE and activate its Dart and Flutter plugins. VS Code may work as an alternative, but this is not recommended.
### Flutter
Install [Flutter](https://docs.flutter.dev/get-started/install) 3.22.1 on your Mac host by following [these instructions](https://docs.flutter.dev/get-started/install/macos). Run `flutter doctor` in a terminal to confirm its installation.
Install [Flutter](https://docs.flutter.dev/get-started/install) 3.29.2 on your Mac host by following [these instructions](https://docs.flutter.dev/get-started/install/macos). Run `flutter doctor` in a terminal to confirm its installation.
### Build plugins and configure
#### Building plugins for iOS
@ -272,35 +276,27 @@ Install the following libraries:
sudo apt-get install libgtk2.0-dev
```
You will also need to install MXE on the WSL2 Ubuntu 20.04 host and can do so by running `stack_wallet/scripts/windows/deps.sh`:
```
./stack_wallet/scripts/windows/deps.sh
```
The WSL2 host may optionally be navigated to the `stack_wallet` repository on the Windows host in order to build the plugins in-place and skip the next section in which you copy the `dll`s from WSL2 to Windows. Then build windows `dll` libraries by running the following script on the WSL2 Ubuntu 20.04 host:
- `stack_wallet/scripts/windows/build_all.sh`
Copy the resulting `dll`s to their respective positions on the Windows host:
If the DLLs were built on the WSL filesystem instead of on Windows, copy the resulting `dll`s to their respective positions on the Windows host:
- `stack_wallet/crypto_plugins/flutter_libepiccash/scripts/windows/build/libepic_cash_wallet.dll`
- `stack_wallet/crypto_plugins/flutter_liblelantus/scripts/windows/build/libmobileliblelantus.dll`
<!--
- `stack_wallet/crypto_plugins/flutter_libmonero/scripts/windows/build/libcw_monero.dll`
- `stack_wallet/crypto_plugins/flutter_libmonero/scripts/windows/build/libcw_wownero.dll`
-->
<!-- TODO: script the copying or installation of libraries from WSL2 to the parent Windows host -->
Frostdart will be built by the Windows host later.
### Install Flutter on Windows host
Install Flutter 3.22.1 on your Windows host (not in WSL2) by [following their guide](https://docs.flutter.dev/get-started/install/windows/desktop?tab=download#install-the-flutter-sdk) or by cloning https://github.com/flutter/flutter, checking out the `3.22.1` tag, and adding its `flutter/bin` folder to your PATH as in
Install Flutter 3.29.2 on your Windows host (not in WSL2) by [following their guide](https://docs.flutter.dev/get-started/install/windows/desktop?tab=download#install-the-flutter-sdk) or by cloning https://github.com/flutter/flutter, checking out the `3.29.2` tag, and adding its `flutter/bin` folder to your PATH as in
```bat
@echo off
set "FLUTTER_DIR=%USERPROFILE%\development\flutter"
git clone https://github.com/flutter/flutter.git "%FLUTTER_DIR%"
cd /d "%FLUTTER_DIR%"
git checkout 3.22.1
git checkout 3.29.2
setx PATH "%PATH%;%FLUTTER_DIR%\bin"
echo Flutter setup completed. Please restart your command prompt.
```
@ -310,9 +306,9 @@ Run `flutter doctor` in PowerShell to confirm its installation.
### Rust
Install [Rust](https://www.rust-lang.org/tools/install) on the Windows host (not in WSL2). Download the installer from [rustup.rs](https://rustup.rs), make sure it works on the commandline (you may need to open a new terminal), and install the following versions:
```
rustup install 1.67.1 1.72.0 1.73.0
rustup default 1.67.1
cargo install cargo-ndk --version 2.12.7 --locked
rustup install 1.85.1 1.81.0
rustup default 1.85.1
cargo install cargo-ndk
```
### Windows SDK and Developer Mode

1
fastlane/Appfile Normal file
View file

@ -0,0 +1 @@
package_name("com.cypherstack.stackwallet")

View file

@ -0,0 +1,11 @@
Stack Wallet is a fully open source cryptocurrency wallet. With an easy to use user interface and quick and speedy transactions, this wallet is ideal for anyone no matter how much they know about the cryptocurrency space. The app is actively maintained to provide new user friendly features.
Highlights include:
- 10 Different cryptocurrencies
- All private keys and seeds stay on device and are never shared.
- Easy backup and restore feature to save all the information that's important to you.
- Trading cryptocurrencies through our partners.
- Custom address book
- Favorite wallets with fast syncing
- Custom Nodes.
- Open source software.

Binary file not shown.

After

(image error) Size: 26 KiB

View file

@ -0,0 +1 @@
An open source, non-custodial cryptocurrency wallet.

View file

@ -1 +0,0 @@
MoneroWallet

View file

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>23E224</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>MoneroWallet</string>
<key>CFBundleIdentifier</key>
<string>com.cypherstack.MoneroWallet</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MoneroWallet</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>???</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>21E210</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>DTPlatformVersion</key>
<string>17.4</string>
<key>DTSDKBuild</key>
<string>21E210</string>
<key>DTSDKName</key>
<string>iphoneos17.4</string>
<key>DTXcode</key>
<string>1530</string>
<key>DTXcodeBuild</key>
<string>15E204a</string>
<key>MinimumOSVersion</key>
<string>16.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
</dict>
</plist>

View file

@ -3,12 +3,14 @@ PODS:
- Flutter
- MTBBarcodeScanner
- SwiftProtobuf
- coinlib_flutter (0.3.2):
- coinlib_flutter (0.5.0):
- Flutter
- FlutterMacOS
- connectivity_plus (0.0.1):
- Flutter
- ReachabilitySwift
- cs_monero_flutter_libs_ios (0.0.1):
- Flutter
- device_info_plus (0.0.1):
- Flutter
- devicelocale (0.0.1):
@ -50,8 +52,6 @@ PODS:
- Flutter (1.0.0)
- flutter_libepiccash (0.0.1):
- Flutter
- flutter_libmonero (0.0.1):
- Flutter
- flutter_libsparkmobile (0.0.1):
- Flutter
- flutter_local_notifications (0.0.1):
@ -67,15 +67,16 @@ PODS:
- Flutter
- lelantus (0.0.1):
- Flutter
- local_auth (0.0.1):
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
- MTBBarcodeScanner (5.0.11)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.1.1):
- permission_handler_apple (9.3.0):
- Flutter
- ReachabilitySwift (5.0.0)
- SDWebImage (5.13.2):
@ -83,14 +84,14 @@ PODS:
- SDWebImage/Core (5.13.2)
- share_plus (0.0.1):
- Flutter
- sqlite3 (3.46.0):
- sqlite3/common (= 3.46.0)
- sqlite3/common (3.46.0)
- sqlite3/fts5 (3.46.0):
- "sqlite3 (3.46.0+1)":
- "sqlite3/common (= 3.46.0+1)"
- "sqlite3/common (3.46.0+1)"
- "sqlite3/fts5 (3.46.0+1)":
- sqlite3/common
- sqlite3/perf-threadsafe (3.46.0):
- "sqlite3/perf-threadsafe (3.46.0+1)":
- sqlite3/common
- sqlite3/rtree (3.46.0):
- "sqlite3/rtree (3.46.0+1)":
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
@ -106,19 +107,21 @@ PODS:
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
- wakelock (0.0.1):
- wakelock_plus (0.0.1):
- Flutter
- xelis_flutter (0.0.1):
- Flutter
DEPENDENCIES:
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- coinlib_flutter (from `.symlinks/plugins/coinlib_flutter/darwin`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- cs_monero_flutter_libs_ios (from `.symlinks/plugins/cs_monero_flutter_libs_ios/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- flutter_libepiccash (from `.symlinks/plugins/flutter_libepiccash/ios`)
- flutter_libmonero (from `.symlinks/plugins/flutter_libmonero/ios`)
- flutter_libsparkmobile (from `.symlinks/plugins/flutter_libsparkmobile/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
@ -127,7 +130,7 @@ DEPENDENCIES:
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`)
- lelantus (from `.symlinks/plugins/lelantus/ios`)
- local_auth (from `.symlinks/plugins/local_auth/ios`)
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
@ -136,7 +139,8 @@ DEPENDENCIES:
- stack_wallet_backup (from `.symlinks/plugins/stack_wallet_backup/ios`)
- tor_ffi_plugin (from `.symlinks/plugins/tor_ffi_plugin/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
- xelis_flutter (from `.symlinks/plugins/xelis_flutter/ios`)
SPEC REPOS:
trunk:
@ -156,6 +160,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/coinlib_flutter/darwin"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
cs_monero_flutter_libs_ios:
:path: ".symlinks/plugins/cs_monero_flutter_libs_ios/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
devicelocale:
@ -166,8 +172,6 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_libepiccash:
:path: ".symlinks/plugins/flutter_libepiccash/ios"
flutter_libmonero:
:path: ".symlinks/plugins/flutter_libmonero/ios"
flutter_libsparkmobile:
:path: ".symlinks/plugins/flutter_libsparkmobile/ios"
flutter_local_notifications:
@ -184,8 +188,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/isar_flutter_libs/ios"
lelantus:
:path: ".symlinks/plugins/lelantus/ios"
local_auth:
:path: ".symlinks/plugins/local_auth/ios"
local_auth_darwin:
:path: ".symlinks/plugins/local_auth_darwin/darwin"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
@ -202,46 +206,48 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/tor_ffi_plugin/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
wakelock:
:path: ".symlinks/plugins/wakelock/ios"
wakelock_plus:
:path: ".symlinks/plugins/wakelock_plus/ios"
xelis_flutter:
:path: ".symlinks/plugins/xelis_flutter/ios"
SPEC CHECKSUMS:
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
coinlib_flutter: 6abec900d67762a6e7ccfd567a3cd3ae00bbee35
coinlib_flutter: 9275e8255ef67d3da33beb6e117d09ced4f46eb5
connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea
devicelocale: b22617f40038496deffba44747101255cee005b0
cs_monero_flutter_libs_ios: fd353631682247f72a36493ff060d4328d6f720d
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: ce3938a0df3cc1ef404671531facef740d03f920
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_libepiccash: 36241aa7d3126f6521529985ccb3dc5eaf7bb317
flutter_libmonero: da68a616b73dd0374a8419c684fa6b6df2c44ffe
flutter_libsparkmobile: 6373955cc3327a926d17059e7405dde2fb12f99f
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
frostdart: 4c72b69ccac2f13ede744107db046a125acce597
integration_test: 13825b8a9334a850581300559b8839134b124670
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
isar_flutter_libs: fdf730ca925d05687f36d7f1d355e482529ed097
lelantus: 417f0221260013dfc052cae9cf4b741b6479edba
local_auth: 1740f55d7af0a2e2a8684ce225fe79d8931e808c
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
sqlite3: 154b084339ede06960a5b3c8160066adc9176b7d
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630
sqlite3_flutter_libs: 0d611efdf6d1c9297d5ab03dab21b75aeebdae31
stack_wallet_backup: 5b8563aba5d8ffbf2ce1944331ff7294a0ec7c03
SwiftProtobuf: 6ef3f0e422ef90d6605ca20b21a94f6c1324d6b3
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
tor_ffi_plugin: d80e291b649379c8176e1be739e49be007d4ef93
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
PODFILE CHECKSUM: 57c8aed26fba39d3ec9424816221f294a07c58eb
COCOAPODS: 1.15.2
COCOAPODS: 1.16.2

View file

@ -48,6 +48,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View file

@ -1,7 +1,7 @@
import UIKit
import Flutter
@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,

View file

@ -1 +0,0 @@
WowneroWallet

View file

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>23E224</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>WowneroWallet</string>
<key>CFBundleIdentifier</key>
<string>com.cypherstack.WowneroWallet</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>WowneroWallet</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>???</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>21E210</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>DTPlatformVersion</key>
<string>17.4</string>
<key>DTSDKBuild</key>
<string>21E210</string>
<key>DTSDKName</key>
<string>iphoneos17.4</string>
<key>DTXcode</key>
<string>1530</string>
<key>DTXcodeBuild</key>
<string>15E204a</string>
<key>MinimumOSVersion</key>
<string>16.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
</dict>
</plist>

View file

@ -27,6 +27,8 @@ abstract class AppConfig {
static List<CryptoCurrency> get coins => _supportedCoins;
static ({String from, String to}) get swapDefaults => _swapDefaults;
static bool get isSingleCoinApp => coins.length == 1;
static CryptoCurrency? getCryptoCurrencyFor(String coinIdentifier) {

View file

@ -29,6 +29,8 @@ import '../utilities/constants.dart';
import '../utilities/flutter_secure_storage_interface.dart';
import '../utilities/logger.dart';
import '../utilities/prefs.dart';
import '../utilities/stack_file_system.dart';
import '../utilities/util.dart';
import '../wallets/crypto_currency/crypto_currency.dart';
import 'hive/db.dart';
import 'isar/main_db.dart';
@ -43,10 +45,7 @@ class DbVersionMigrator with WalletDB {
// safe to skip to v11 for campfire
fromVersion = 11;
}
Logging.instance.log(
"Running migrate fromVersion $fromVersion",
level: LogLevel.Warning,
);
Logging.instance.i("Running migrate fromVersion $fromVersion");
switch (fromVersion) {
case 0:
await DB.instance.hive.openBox<dynamic>(DB.boxNameAllWalletsData);
@ -77,6 +76,8 @@ class DbVersionMigrator with WalletDB {
name: e.name,
id: e.id,
useSSL: e.useSSL,
torEnabled: e.torEnabled,
clearnetEnabled: e.clearnetEnabled,
),
)
.toList();
@ -88,6 +89,8 @@ class DbVersionMigrator with WalletDB {
name: node.name,
id: node.id,
useSSL: node.useSSL,
torEnabled: node.torEnabled,
clearnetEnabled: node.clearnetEnabled,
),
prefs: prefs,
failovers: failovers,
@ -96,12 +99,13 @@ class DbVersionMigrator with WalletDB {
try {
latestSetId = await client.getLelantusLatestCoinId();
} catch (e) {
} catch (e, s) {
// default to 2 for now
latestSetId = 2;
Logging.instance.log(
Logging.instance.w(
"Failed to fetch latest coin id during firo db migrate: $e \nUsing a default value of 2",
level: LogLevel.Warning,
error: e,
stackTrace: s,
);
}
}
@ -140,7 +144,6 @@ class DbVersionMigrator with WalletDB {
),
});
}
Logger.print("newcoins $coins", normalLength: false);
await DB.instance.put<dynamic>(
boxName: walletInfo.walletId,
key: '_lelantus_coins',
@ -439,6 +442,20 @@ class DbVersionMigrator with WalletDB {
// try to continue migrating
return await migrate(13, secureStore: secureStore);
case 13:
// migrate
await _v13(secureStore);
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 14,
);
// try to continue migrating
return await migrate(14, secureStore: secureStore);
default:
// finally return
return;
@ -730,4 +747,31 @@ class DbVersionMigrator with WalletDB {
);
}
}
Future<void> _v13(SecureStorageInterface secureStore) async {
if (!(Util.isArmLinux || Util.isTestEnv)) {
// open logs db
final isar = await Isar.open(
[isar_models.LogSchema],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
inspector: false,
maxSizeMiB: 512,
);
// fetch all logs
final allLogs = await isar.logs.where().findAll();
// migrate to simple file based logs. Date/time may be out of order
for (final log in allLogs) {
Logging.instance.log(
log.logLevel.getLoggerLevel(),
"MIGRATED LOG::=> ${log.message}",
time: DateTime.fromMillisecondsSinceEpoch(log.timestampInMillisUTC),
);
}
// finally delete logs db
await isar.close(deleteFromDisk: true);
}
}
}

View file

@ -10,7 +10,7 @@
import 'dart:isolate';
import 'package:cw_core/wallet_info.dart' as xmr;
import 'package:compat/compat.dart' as lib_monero_compat;
import 'package:hive/hive.dart' show Box;
import 'package:hive/src/hive_impl.dart';
import 'package:mutex/mutex.dart';
@ -71,7 +71,7 @@ class DB {
Box<Trade>? _boxTradesV2;
Box<String>? _boxTradeNotes;
Box<String>? _boxFavoriteWallets;
Box<xmr.WalletInfo>? _walletInfoSource;
Box<lib_monero_compat.WalletInfo>? _walletInfoSource;
Box<dynamic>? _boxPrefs;
Box<TradeWalletLookup>? _boxTradeLookup;
Box<dynamic>? _boxDBInfo;
@ -85,7 +85,8 @@ class DB {
final Map<String, Box<dynamic>> _getSparkUsedCoinsTagsCacheBoxes = {};
// exposed for monero
Box<xmr.WalletInfo> get moneroWalletInfoBox => _walletInfoSource!;
Box<lib_monero_compat.WalletInfo> get moneroWalletInfoBox =>
_walletInfoSource!;
// mutex for stack backup
final mutex = Mutex();
@ -147,8 +148,8 @@ class DB {
_boxTradesV2 = await hive.openBox<Trade>(boxNameTradesV2);
_boxTradeNotes = await hive.openBox<String>(boxNameTradeNotes);
_boxTradeLookup = await hive.openBox<TradeWalletLookup>(boxNameTradeLookup);
_walletInfoSource =
await hive.openBox<xmr.WalletInfo>(xmr.WalletInfo.boxName);
_walletInfoSource = await hive.openBox<lib_monero_compat.WalletInfo>(
lib_monero_compat.WalletInfo.boxName);
_boxFavoriteWallets = await hive.openBox<String>(boxNameFavoriteWallets);
await Future.wait([
@ -165,9 +166,10 @@ class DB {
AppConfig.getCryptoCurrencyFor(jsonObject["coin"] as String);
return false;
} catch (e, s) {
Logging.instance.log(
Logging.instance.e(
"Error, ${jsonObject["coin"]} does not exist, $name wallet cannot be loaded",
level: LogLevel.Error,
error: e,
stackTrace: s,
);
return true;
}
@ -342,7 +344,7 @@ class DB {
await DB.instance.deleteBoxFromDisk(boxName: "theme");
return true;
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Error);
Logging.instance.e("$e $s", error: e, stackTrace: s);
return false;
}
}

View file

@ -2,13 +2,13 @@ import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart';
import 'package:mutex/mutex.dart';
import 'package:sqlite3/sqlite3.dart';
import 'package:uuid/uuid.dart';
import '../../electrumx_rpc/electrumx_client.dart';
import '../../models/electrumx_response/spark_models.dart';
import '../../utilities/extensions/extensions.dart';
import '../../utilities/logger.dart';
import '../../utilities/stack_file_system.dart';
@ -19,18 +19,8 @@ part 'firo_cache_reader.dart';
part 'firo_cache_worker.dart';
part 'firo_cache_writer.dart';
/// Temporary debugging log function for this file
void _debugLog(Object? object) {
if (kDebugMode) {
Logging.instance.log(
object,
level: LogLevel.Debug,
);
}
}
abstract class _FiroCache {
static const int _setCacheVersion = 1;
static const int _setCacheVersion = 2;
static const int _tagsCacheVersion = 2;
static final networks = [
@ -115,7 +105,8 @@ abstract class _FiroCache {
VACUUM;
""",
);
_debugLog(
Logging.instance.d(
"_deleteAllCache() "
"duration = ${DateTime.now().difference(start)}",
);
@ -134,7 +125,7 @@ abstract class _FiroCache {
blockHash TEXT NOT NULL,
setHash TEXT NOT NULL,
groupId INTEGER NOT NULL,
timestampUTC INTEGER NOT NULL,
size INTEGER NOT NULL,
UNIQUE (blockHash, setHash, groupId)
);
@ -143,7 +134,8 @@ abstract class _FiroCache {
serialized TEXT NOT NULL,
txHash TEXT NOT NULL,
context TEXT NOT NULL,
UNIQUE(serialized, txHash, context)
groupId INTEGER NOT NULL,
UNIQUE(serialized, txHash, context, groupId)
);
CREATE TABLE SparkSetCoins (

View file

@ -6,6 +6,8 @@ typedef LTagPair = ({String tag, String txid});
/// background isolate and [FiroCacheCoordinator] should manage that isolate
abstract class FiroCacheCoordinator {
static final Map<CryptoCurrencyNetwork, _FiroCacheWorker> _workers = {};
static final Map<CryptoCurrencyNetwork, Mutex> _tagLocks = {};
static final Map<CryptoCurrencyNetwork, Mutex> _setLocks = {};
static bool _init = false;
static Future<void> init() async {
@ -15,6 +17,8 @@ abstract class FiroCacheCoordinator {
_init = true;
await _FiroCache.init();
for (final network in _FiroCache.networks) {
_tagLocks[network] = Mutex();
_setLocks[network] = Mutex();
_workers[network] = await _FiroCacheWorker.spawn(network);
}
}
@ -31,11 +35,17 @@ abstract class FiroCacheCoordinator {
final usedTagsCacheFile = File(
"${dir.path}/${_FiroCache.sparkUsedTagsCacheFileName(network)}",
);
final int bytes =
((await setCacheFile.exists()) ? await setCacheFile.length() : 0) +
((await usedTagsCacheFile.exists())
? await usedTagsCacheFile.length()
: 0);
final setSize =
(await setCacheFile.exists()) ? await setCacheFile.length() : 0;
final tagsSize = (await usedTagsCacheFile.exists())
? await usedTagsCacheFile.length()
: 0;
Logging.instance.d("Spark cache used tags size: $tagsSize");
Logging.instance.d("Spark cache anon set size: $setSize");
final int bytes = tagsSize + setSize;
if (bytes < 1024) {
return '$bytes B';
@ -55,43 +65,93 @@ abstract class FiroCacheCoordinator {
ElectrumXClient client,
CryptoCurrencyNetwork network,
) async {
final count = await FiroCacheCoordinator.getUsedCoinTagsCount(network);
final unhashedTags = await client.getSparkUnhashedUsedCoinsTagsWithTxHashes(
startNumber: count,
);
if (unhashedTags.isNotEmpty) {
await _workers[network]!.runTask(
FCTask(
func: FCFuncName._updateSparkUsedTagsWith,
data: unhashedTags,
),
await _tagLocks[network]!.protect(() async {
final count = await FiroCacheCoordinator.getUsedCoinTagsCount(network);
final unhashedTags =
await client.getSparkUnhashedUsedCoinsTagsWithTxHashes(
startNumber: count,
);
}
if (unhashedTags.isNotEmpty) {
await _workers[network]!.runTask(
FCTask(
func: FCFuncName._updateSparkUsedTagsWith,
data: unhashedTags,
),
);
}
});
}
static Future<void> runFetchAndUpdateSparkAnonSetCacheForGroupId(
int groupId,
ElectrumXClient client,
CryptoCurrencyNetwork network,
void Function(int countFetched, int totalCount)? progressUpdated,
) async {
final blockhashResult =
await FiroCacheCoordinator.getLatestSetInfoForGroupId(
groupId,
network,
);
final blockHash = blockhashResult?.blockHash ?? "";
await _setLocks[network]!.protect(() async {
const sectorSize =
1500; // chosen as a somewhat decent value. Could be changed in the future if wanted/needed
final prevMeta = await FiroCacheCoordinator.getLatestSetInfoForGroupId(
groupId,
network,
);
final json = await client.getSparkAnonymitySet(
coinGroupId: groupId.toString(),
startBlockHash: blockHash.toHexReversedFromBase64,
);
final prevSize = prevMeta?.size ?? 0;
await _workers[network]!.runTask(
FCTask(
func: FCFuncName._updateSparkAnonSetCoinsWith,
data: (groupId, json),
),
);
final meta = await client.getSparkAnonymitySetMeta(
coinGroupId: groupId,
);
progressUpdated?.call(prevSize, meta.size);
if (prevMeta?.blockHash == meta.blockHash) {
Logging.instance.d("prevMeta?.blockHash == meta.blockHash");
return;
}
final numberOfCoinsToFetch = meta.size - prevSize;
final fullSectorCount = numberOfCoinsToFetch ~/ sectorSize;
final remainder = numberOfCoinsToFetch % sectorSize;
final List<dynamic> coins = [];
for (int i = 0; i < fullSectorCount; i++) {
final start = (i * sectorSize);
final data = await client.getSparkAnonymitySetBySector(
coinGroupId: groupId,
latestBlock: meta.blockHash,
startIndex: start,
endIndex: start + sectorSize,
);
progressUpdated?.call(start + sectorSize, numberOfCoinsToFetch);
coins.addAll(data);
}
if (remainder > 0) {
final data = await client.getSparkAnonymitySetBySector(
coinGroupId: groupId,
latestBlock: meta.blockHash,
startIndex: numberOfCoinsToFetch - remainder,
endIndex: numberOfCoinsToFetch,
);
progressUpdated?.call(numberOfCoinsToFetch, numberOfCoinsToFetch);
coins.addAll(data);
}
final result = coins
.map((e) => RawSparkCoin.fromRPCResponse(e as List, groupId))
.toList();
await _workers[network]!.runTask(
FCTask(
func: FCFuncName._updateSparkAnonSetCoinsWith,
data: (meta, result),
),
);
});
}
// ===========================================================================
@ -165,28 +225,29 @@ abstract class FiroCacheCoordinator {
);
}
static Future<
List<
({
String serialized,
String txHash,
String context,
})>> getSetCoinsForGroupId(
static Future<List<RawSparkCoin>> getSetCoinsForGroupId(
int groupId, {
int? newerThanTimeStamp,
String? afterBlockHash,
required CryptoCurrencyNetwork network,
}) async {
final resultSet = await _Reader._getSetCoinsForGroupId(
groupId,
db: _FiroCache.setCacheDB(network),
newerThanTimeStamp: newerThanTimeStamp,
);
final resultSet = afterBlockHash == null
? await _Reader._getSetCoinsForGroupId(
groupId,
db: _FiroCache.setCacheDB(network),
)
: await _Reader._getSetCoinsForGroupIdAndBlockHash(
groupId,
afterBlockHash,
db: _FiroCache.setCacheDB(network),
);
return resultSet
.map(
(row) => (
(row) => RawSparkCoin(
serialized: row["serialized"] as String,
txHash: row["txHash"] as String,
context: row["context"] as String,
groupId: groupId,
),
)
.toList()
@ -194,12 +255,7 @@ abstract class FiroCacheCoordinator {
.toList();
}
static Future<
({
String blockHash,
String setHash,
int timestampUTC,
})?> getLatestSetInfoForGroupId(
static Future<SparkAnonymitySetMeta?> getLatestSetInfoForGroupId(
int groupId,
CryptoCurrencyNetwork network,
) async {
@ -212,10 +268,11 @@ abstract class FiroCacheCoordinator {
return null;
}
return (
return SparkAnonymitySetMeta(
coinGroupId: groupId,
blockHash: result.first["blockHash"] as String,
setHash: result.first["setHash"] as String,
timestampUTC: result.first["timestampUTC"] as int,
size: result.first["size"] as int,
);
}

View file

@ -8,21 +8,15 @@ abstract class _Reader {
static Future<ResultSet> _getSetCoinsForGroupId(
int groupId, {
required Database db,
int? newerThanTimeStamp,
}) async {
String query = """
SELECT sc.serialized, sc.txHash, sc.context
final query = """
SELECT sc.serialized, sc.txHash, sc.context, sc.groupId
FROM SparkSet AS ss
JOIN SparkSetCoins AS ssc ON ss.id = ssc.setId
JOIN SparkCoin AS sc ON ssc.coinId = sc.id
WHERE ss.groupId = $groupId
WHERE ss.groupId = $groupId;
""";
if (newerThanTimeStamp != null) {
query += " AND ss.timestampUTC"
" > $newerThanTimeStamp";
}
return db.select("$query;");
}
@ -31,16 +25,45 @@ abstract class _Reader {
required Database db,
}) async {
final query = """
SELECT ss.blockHash, ss.setHash, ss.timestampUTC
SELECT ss.blockHash, ss.setHash, ss.size
FROM SparkSet ss
WHERE ss.groupId = $groupId
ORDER BY ss.timestampUTC DESC
ORDER BY ss.size DESC
LIMIT 1;
""";
return db.select("$query;");
}
static Future<ResultSet> _getSetCoinsForGroupIdAndBlockHash(
int groupId,
String blockHash, {
required Database db,
}) async {
const query = """
WITH TargetBlock AS (
SELECT id
FROM SparkSet
WHERE blockHash = ?
),
TargetSets AS (
SELECT id AS setId
FROM SparkSet
WHERE groupId = ? AND id > (SELECT id FROM TargetBlock)
)
SELECT
SparkCoin.serialized,
SparkCoin.txHash,
SparkCoin.context,
SparkCoin.groupId
FROM SparkSetCoins
JOIN SparkCoin ON SparkSetCoins.coinId = SparkCoin.id
WHERE SparkSetCoins.setId IN (SELECT setId FROM TargetSets);
""";
return db.select("$query;", [blockHash, groupId]);
}
static Future<bool> _checkSetInfoForGroupIdExists(
int groupId, {
required Database db,

View file

@ -48,7 +48,11 @@ class _FiroCacheWorker {
try {
await Isolate.spawn(
_startWorkerIsolate,
(initPort.sendPort, setCacheFilePath, usedTagsCacheFilePath),
(
initPort.sendPort,
setCacheFilePath,
usedTagsCacheFilePath,
),
);
} catch (_) {
initPort.close();
@ -90,7 +94,8 @@ class _FiroCacheWorker {
final FCResult result;
switch (task.func) {
case FCFuncName._updateSparkAnonSetCoinsWith:
final data = task.data as (int, Map<String, dynamic>);
final data =
task.data as (SparkAnonymitySetMeta, List<RawSparkCoin>);
result = _updateSparkAnonSetCoinsWith(
setCacheDb,
data.$2,

View file

@ -19,8 +19,8 @@ FCResult _updateSparkUsedTagsWith(
) {
// hash the tags here since this function is called in a background isolate
final hashedTags = LibSpark.hashTags(
base64Tags: tags.map((e) => e[0] as String),
);
base64Tags: tags.map((e) => e[0] as String).toSet(),
).toList();
if (hashedTags.isEmpty) {
// nothing to add, return early
@ -52,29 +52,13 @@ FCResult _updateSparkUsedTagsWith(
// ================== write to spark anon set cache ==========================
/// update the sqlite cache
/// Expected json format:
/// {
/// "blockHash": "someBlockHash",
/// "setHash": "someSetHash",
/// "coins": [
/// ["serliazed1", "hash1", "context1"],
/// ["serliazed2", "hash2", "context2"],
/// ...
/// ["serliazed3", "hash3", "context3"],
/// ["serliazed4", "hash4", "context4"],
/// ],
/// }
///
/// returns true if successful, otherwise false
FCResult _updateSparkAnonSetCoinsWith(
Database db,
Map<String, dynamic> json,
int groupId,
final List<RawSparkCoin> coinsRaw,
SparkAnonymitySetMeta meta,
) {
final blockHash = json["blockHash"] as String;
final setHash = json["setHash"] as String;
final coinsRaw = json["coins"] as List;
if (coinsRaw.isEmpty) {
// no coins to actually insert
return FCResult(success: true);
@ -87,9 +71,9 @@ FCResult _updateSparkAnonSetCoinsWith(
WHERE blockHash = ? AND setHash = ? AND groupId = ?;
""",
[
blockHash,
setHash,
groupId,
meta.blockHash,
meta.setHash,
meta.coinGroupId,
],
);
@ -98,59 +82,28 @@ FCResult _updateSparkAnonSetCoinsWith(
return FCResult(success: true);
}
final coins = coinsRaw
.map(
(e) => [
e[0] as String,
e[1] as String,
e[2] as String,
],
)
.toList()
.reversed;
final timestamp = DateTime.now().toUtc().millisecondsSinceEpoch ~/ 1000;
final coins = coinsRaw.reversed;
db.execute("BEGIN;");
try {
db.execute(
"""
INSERT INTO SparkSet (blockHash, setHash, groupId, timestampUTC)
INSERT INTO SparkSet (blockHash, setHash, groupId, size)
VALUES (?, ?, ?, ?);
""",
[blockHash, setHash, groupId, timestamp],
[meta.blockHash, meta.setHash, meta.coinGroupId, meta.size],
);
final setId = db.lastInsertRowId;
for (final coin in coins) {
int coinId;
try {
// try to insert and get row id
db.execute(
"""
INSERT INTO SparkCoin (serialized, txHash, context)
VALUES (?, ?, ?);
db.execute(
"""
INSERT INTO SparkCoin (serialized, txHash, context, groupId)
VALUES (?, ?, ?, ?);
""",
coin,
);
coinId = db.lastInsertRowId;
} on SqliteException catch (e) {
// if there already is a matching coin in the db
// just grab its row id
if (e.extendedResultCode == 2067) {
final result = db.select(
"""
SELECT id
FROM SparkCoin
WHERE serialized = ? AND txHash = ? AND context = ?;
""",
coin,
);
coinId = result.first["id"] as int;
} else {
rethrow;
}
}
[coin.serialized, coin.txHash, coin.context, coin.groupId],
);
final coinId = db.lastInsertRowId;
// finally add the row id to the newly added set
db.execute(

View file

@ -100,17 +100,17 @@ class CachedElectrumXClient {
}
// save set to db
await box.put(groupId, set);
Logging.instance.log(
Logging.instance.d(
"Updated current anonymity set for ${cryptoCurrency.identifier} with group ID $groupId",
level: LogLevel.Info,
);
}
return set;
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getAnonymitySet(): $e\n$s",
level: LogLevel.Error,
Logging.instance.e(
"Failed to process CachedElectrumX.getAnonymitySet(): ",
error: e,
stackTrace: s,
);
rethrow;
}
@ -155,16 +155,17 @@ class CachedElectrumXClient {
await box.put(txHash, result);
}
// Logging.instance.log("using fetched result", level: LogLevel.Info);
// Logging.instance.log("using fetched result");
return result;
} else {
// Logging.instance.log("using cached result", level: LogLevel.Info);
// Logging.instance.log("using cached result");
return Map<String, dynamic>.from(cachedTx);
}
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",
level: LogLevel.Error,
Logging.instance.e(
"Failed to process CachedElectrumX.getTransaction(): ",
error: e,
stackTrace: s,
);
rethrow;
}
@ -212,9 +213,10 @@ class CachedElectrumXClient {
return resultingList;
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getUsedCoinSerials(): $e\n$s",
level: LogLevel.Error,
Logging.instance.e(
"Failed to process CachedElectrumX.getUsedCoinSerials(): ",
error: e,
stackTrace: s,
);
rethrow;
}

View file

@ -1,6 +1,10 @@
import 'dart:async';
import 'package:electrum_adapter/electrum_adapter.dart';
import '../utilities/logger.dart';
import '../utilities/prefs.dart';
import '../utilities/tor_plain_net_option_enum.dart';
import '../wallets/crypto_currency/crypto_currency.dart';
class ClientManager {
@ -8,6 +12,7 @@ class ClientManager {
static final ClientManager sharedInstance = ClientManager._();
final Map<String, ElectrumClient> _map = {};
final Map<String, TorPlainNetworkOption> _mapNet = {};
final Map<String, int> _heights = {};
final Map<String, StreamSubscription<BlockHeader>> _subscriptions = {};
final Map<String, Completer<int>> _heightCompleters = {};
@ -22,28 +27,54 @@ class ClientManager {
ElectrumClient? getClient({
required CryptoCurrency cryptoCurrency,
}) =>
_map[_keyHelper(cryptoCurrency)];
required TorPlainNetworkOption netType,
}) {
final _key = _keyHelper(cryptoCurrency);
void addClient(
if (netType == _mapNet[_key]) {
return _map[_key];
} else {
return null;
}
}
Future<void> addClient(
ElectrumClient client, {
required CryptoCurrency cryptoCurrency,
}) {
required TorPlainNetworkOption netType,
}) async {
final key = _keyHelper(cryptoCurrency);
if (_map[key] != null) {
throw Exception("ElectrumX Client for $key already exists.");
if (_mapNet[key] == netType) {
throw Exception(
"ElectrumX Client for $key and $netType already exists.",
);
}
await remove(cryptoCurrency: cryptoCurrency);
_map[key] = client;
_mapNet[key] = netType;
} else {
_map[key] = client;
_mapNet[key] = netType;
}
_heightCompleters[key] = Completer<int>();
_subscriptions[key] = client.subscribeHeaders().listen((event) {
_heights[key] = event.height;
_subscriptions[key] = client.subscribeHeaders().listen(
(event) {
_heights[key] = event.height;
if (!_heightCompleters[key]!.isCompleted) {
_heightCompleters[key]!.complete(event.height);
}
});
if (!_heightCompleters[key]!.isCompleted) {
_heightCompleters[key]!.complete(event.height);
}
},
onError: (Object err, StackTrace s) => Logging.instance.e(
"ClientManager listen",
error: err,
stackTrace: s,
),
);
}
Future<int> getChainHeightFor(CryptoCurrency cryptoCurrency) async {
@ -60,10 +91,24 @@ class ClientManager {
);
}
if (Prefs.instance.useTor) {
if (_mapNet[key]! == TorPlainNetworkOption.clear) {
throw Exception(
"Non-TOR only client for $key found.",
);
}
} else {
if (_mapNet[key]! == TorPlainNetworkOption.tor) {
throw Exception(
"TOR only client for $key found.",
);
}
}
return _heights[key] ?? await _heightCompleters[key]!.future;
}
Future<ElectrumClient?> remove({
Future<(ElectrumClient?, TorPlainNetworkOption?)> remove({
required CryptoCurrency cryptoCurrency,
}) async {
final key = _keyHelper(cryptoCurrency);
@ -72,7 +117,7 @@ class ClientManager {
_heights.remove(key);
_heightCompleters.remove(key);
return _map.remove(key);
return (_map.remove(key), _mapNet.remove(key));
}
Future<void> closeAll() async {
@ -91,6 +136,7 @@ class ClientManager {
_heightCompleters.clear();
_heights.clear();
_subscriptions.clear();
_mapNet.clear();
_map.clear();
}
}

View file

@ -21,6 +21,7 @@ import 'package:mutex/mutex.dart';
import 'package:stream_channel/stream_channel.dart';
import '../exceptions/electrumx/no_such_transaction.dart';
import '../models/electrumx_response/spark_models.dart';
import '../services/event_bus/events/global/tor_connection_status_changed_event.dart';
import '../services/event_bus/events/global/tor_status_changed_event.dart';
import '../services/event_bus/global_event_bus.dart';
@ -29,19 +30,17 @@ import '../utilities/amount/amount.dart';
import '../utilities/extensions/impl/string.dart';
import '../utilities/logger.dart';
import '../utilities/prefs.dart';
import '../utilities/tor_plain_net_option_enum.dart';
import '../wallets/crypto_currency/crypto_currency.dart';
import '../wallets/crypto_currency/interfaces/electrumx_currency_interface.dart';
import 'client_manager.dart';
typedef SparkMempoolData = ({
String txid,
List<String> serialContext,
List<String> lTags,
List<String> coins,
});
class WifiOnlyException implements Exception {}
class TorOnlyException implements Exception {}
class ClearnetOnlyException implements Exception {}
class ElectrumXNode {
ElectrumXNode({
required this.address,
@ -49,12 +48,16 @@ class ElectrumXNode {
required this.name,
required this.id,
required this.useSSL,
required this.torEnabled,
required this.clearnetEnabled,
});
final String address;
final int port;
final String name;
final String id;
final bool useSSL;
final bool torEnabled;
final bool clearnetEnabled;
factory ElectrumXNode.from(ElectrumXNode node) {
return ElectrumXNode(
@ -63,6 +66,8 @@ class ElectrumXNode {
name: node.name,
id: node.id,
useSSL: node.useSSL,
torEnabled: node.torEnabled,
clearnetEnabled: node.clearnetEnabled,
);
}
@ -74,6 +79,7 @@ class ElectrumXNode {
class ElectrumXClient {
final CryptoCurrency cryptoCurrency;
final TorPlainNetworkOption netType;
String get host => _host;
late String _host;
@ -90,12 +96,13 @@ class ElectrumXClient {
ElectrumClient? getElectrumAdapter() =>
ClientManager.sharedInstance.getClient(
cryptoCurrency: cryptoCurrency,
netType: netType,
);
late Prefs _prefs;
late TorService _torService;
List<ElectrumXNode>? failovers;
late final List<ElectrumXNode> _failovers;
int currentFailoverIndex = -1;
final Duration connectionTimeoutForSpecialCaseJsonRPCClients;
@ -119,6 +126,7 @@ class ElectrumXClient {
required int port,
required bool useSSL,
required Prefs prefs,
required this.netType,
required List<ElectrumXNode> failovers,
required this.cryptoCurrency,
this.connectionTimeoutForSpecialCaseJsonRPCClients =
@ -131,6 +139,7 @@ class ElectrumXClient {
_host = host;
_port = port;
_useSSL = useSSL;
_failovers = failovers;
final bus = globalEventBusForTesting ?? GlobalEventBus.instance;
@ -168,6 +177,7 @@ class ElectrumXClient {
_electrumAdapterChannel = null;
await (await ClientManager.sharedInstance
.remove(cryptoCurrency: cryptoCurrency))
.$1
?.close();
// Also close any chain height services that are currently open.
@ -193,6 +203,10 @@ class ElectrumXClient {
failovers: failovers,
globalEventBusForTesting: globalEventBusForTesting,
cryptoCurrency: cryptoCurrency,
netType: TorPlainNetworkOption.fromNodeData(
node.torEnabled,
node.clearnetEnabled,
),
);
}
@ -219,10 +233,9 @@ class ElectrumXClient {
if (!_prefs.torKillSwitch) {
// Then we'll just proceed and connect to ElectrumX through
// clearnet at the bottom of this function.
Logging.instance.log(
Logging.instance.w(
"Tor preference set but Tor is not enabled, killswitch not set,"
" connecting to Electrum adapter through clearnet",
level: LogLevel.Warning,
);
} else {
// ... But if the killswitch is set, then we throw an exception.
@ -236,6 +249,18 @@ class ElectrumXClient {
// Get the proxy info from the TorService.
proxyInfo = _torService.getProxyInfo();
}
if (netType == TorPlainNetworkOption.clear) {
_electrumAdapterChannel = null;
await ClientManager.sharedInstance
.remove(cryptoCurrency: cryptoCurrency);
}
} else {
if (netType == TorPlainNetworkOption.tor) {
_electrumAdapterChannel = null;
await ClientManager.sharedInstance
.remove(cryptoCurrency: cryptoCurrency);
}
}
// If the current ElectrumAdapterClient is closed, create a new one.
@ -253,9 +278,11 @@ class ElectrumXClient {
usePort = port;
useUseSSL = useSSL;
} else {
useHost = failovers![currentFailoverIndex].address;
usePort = failovers![currentFailoverIndex].port;
useUseSSL = failovers![currentFailoverIndex].useSSL;
_electrumAdapterChannel = null;
await ClientManager.sharedInstance.remove(cryptoCurrency: cryptoCurrency);
useHost = _failovers[currentFailoverIndex].address;
usePort = _failovers[currentFailoverIndex].port;
useUseSSL = _failovers[currentFailoverIndex].useSSL;
}
_electrumAdapterChannel ??= await electrum_adapter.connect(
@ -288,9 +315,10 @@ class ElectrumXClient {
);
}
ClientManager.sharedInstance.addClient(
await ClientManager.sharedInstance.addClient(
newClient,
cryptoCurrency: cryptoCurrency,
netType: netType,
);
}
@ -352,6 +380,10 @@ class ElectrumXClient {
return response;
} on WifiOnlyException {
rethrow;
} on ClearnetOnlyException {
rethrow;
} on TorOnlyException {
rethrow;
} on SocketException {
// likely timed out so then retry
if (retries > 0) {
@ -365,8 +397,17 @@ class ElectrumXClient {
} else {
rethrow;
}
} catch (e) {
if (failovers != null && currentFailoverIndex < failovers!.length - 1) {
} catch (e, s) {
final errorMessage = e.toString();
Logging.instance.w(
"$host $e",
error: e,
stackTrace: s,
);
if (errorMessage.contains("JSON-RPC error")) {
currentFailoverIndex = _failovers.length;
}
if (currentFailoverIndex < _failovers.length - 1) {
currentFailoverIndex++;
return request(
command: command,
@ -442,6 +483,10 @@ class ElectrumXClient {
return response;
} on WifiOnlyException {
rethrow;
} on ClearnetOnlyException {
rethrow;
} on TorOnlyException {
rethrow;
} on SocketException {
// likely timed out so then retry
if (retries > 0) {
@ -455,7 +500,7 @@ class ElectrumXClient {
rethrow;
}
} catch (e) {
if (failovers != null && currentFailoverIndex < failovers!.length - 1) {
if (currentFailoverIndex < _failovers.length - 1) {
currentFailoverIndex++;
return batchRequest(
command: command,
@ -488,9 +533,16 @@ class ElectrumXClient {
return await request(
requestID: requestID,
command: 'server.ping',
requestTimeout: const Duration(seconds: 2),
requestTimeout: const Duration(seconds: 30),
retries: retryCount,
).timeout(const Duration(seconds: 2)) as bool;
).timeout(
const Duration(seconds: 30),
onTimeout: () {
Logging.instance.d(
"ElectrumxClient.ping timed out with retryCount=$retryCount, host=$_host",
);
},
) as bool;
} catch (e) {
rethrow;
}
@ -512,10 +564,7 @@ class ElectrumXClient {
command: 'blockchain.headers.subscribe',
);
if (response == null) {
Logging.instance.log(
"getBlockHeadTip returned null response",
level: LogLevel.Error,
);
Logging.instance.e("getBlockHeadTip returned null response");
throw 'getBlockHeadTip returned null response';
}
return Map<String, dynamic>.from(response as Map);
@ -706,14 +755,15 @@ class ElectrumXClient {
try {
final data = List<Map<String, dynamic>>.from(response[i] as List);
result.add(data);
} catch (e) {
} catch (e, s) {
// to ensure we keep same length of responses as requests/args
// add empty list on error
result.add([]);
Logging.instance.log(
Logging.instance.e(
"getBatchUTXOs failed to parse response=${response[i]}: $e",
level: LogLevel.Error,
error: e,
stackTrace: s,
);
}
}
@ -776,15 +826,13 @@ class ElectrumXClient {
bool verbose = true,
String? requestID,
}) async {
Logging.instance.log(
Logging.instance.d(
"attempting to fetch blockchain.transaction.get...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
final dynamic response = await getElectrumAdapter()!.getTransaction(txHash);
Logging.instance.log(
Logging.instance.d(
"Fetching blockchain.transaction.get finished",
level: LogLevel.Info,
);
if (!verbose) {
@ -813,17 +861,15 @@ class ElectrumXClient {
String blockhash = "",
String? requestID,
}) async {
Logging.instance.log(
Logging.instance.d(
"attempting to fetch lelantus.getanonymityset...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
final Map<String, dynamic> response =
await (getElectrumAdapter() as FiroElectrumClient)
.getLelantusAnonymitySet(groupId: groupId, blockHash: blockhash);
Logging.instance.log(
Logging.instance.d(
"Fetching lelantus.getanonymityset finished",
level: LogLevel.Info,
);
return response;
}
@ -836,16 +882,14 @@ class ElectrumXClient {
dynamic mints,
String? requestID,
}) async {
Logging.instance.log(
Logging.instance.d(
"attempting to fetch lelantus.getmintmetadata...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
final dynamic response = await (getElectrumAdapter() as FiroElectrumClient)
.getLelantusMintData(mints: mints);
Logging.instance.log(
Logging.instance.d(
"Fetching lelantus.getmintmetadata finished",
level: LogLevel.Info,
);
return response;
}
@ -856,9 +900,8 @@ class ElectrumXClient {
String? requestID,
required int startNumber,
}) async {
Logging.instance.log(
Logging.instance.d(
"attempting to fetch lelantus.getusedcoinserials...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
@ -869,9 +912,8 @@ class ElectrumXClient {
response = await (getElectrumAdapter() as FiroElectrumClient)
.getLelantusUsedCoinSerials(startNumber: startNumber);
// TODO add 2 minute timeout.
Logging.instance.log(
Logging.instance.d(
"Fetching lelantus.getusedcoinserials finished",
level: LogLevel.Info,
);
retryCount--;
@ -884,16 +926,14 @@ class ElectrumXClient {
///
/// ex: 1
Future<int> getLelantusLatestCoinId({String? requestID}) async {
Logging.instance.log(
Logging.instance.d(
"attempting to fetch lelantus.getlatestcoinid...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
final int response =
await (getElectrumAdapter() as FiroElectrumClient).getLatestCoinId();
Logging.instance.log(
Logging.instance.d(
"Fetching lelantus.getlatestcoinid finished",
level: LogLevel.Info,
);
return response;
}
@ -927,12 +967,11 @@ class ElectrumXClient {
coinGroupId: coinGroupId,
startBlockHash: startBlockHash,
);
Logging.instance.log(
Logging.instance.d(
"Finished ElectrumXClient.getSparkAnonymitySet(coinGroupId"
"=$coinGroupId, startBlockHash=$startBlockHash). "
"coins.length: ${(response["coins"] as List?)?.length}"
"Duration=${DateTime.now().difference(start)}",
level: LogLevel.Info,
);
return response;
} catch (e) {
@ -970,7 +1009,7 @@ class ElectrumXClient {
// );
//
// return tags;
// } catch (e) {
// } catch (e, s) {
// Logging.instance.log(e, level: LogLevel.Error);
// rethrow;
// }
@ -986,29 +1025,30 @@ class ElectrumXClient {
/// "b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390",
/// ]
/// }
Future<List<Map<String, dynamic>>> getSparkMintMetaData({
String? requestID,
required List<String> sparkCoinHashes,
}) async {
try {
Logging.instance.log(
"attempting to fetch spark.getsparkmintmetadata...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
final List<dynamic> response =
await (getElectrumAdapter() as FiroElectrumClient)
.getSparkMintMetaData(sparkCoinHashes: sparkCoinHashes);
Logging.instance.log(
"Fetching spark.getsparkmintmetadata finished",
level: LogLevel.Info,
);
return List<Map<String, dynamic>>.from(response);
} catch (e) {
Logging.instance.log(e, level: LogLevel.Error);
rethrow;
}
}
/// NOT USED?
// Future<List<Map<String, dynamic>>> getSparkMintMetaData({
// String? requestID,
// required List<String> sparkCoinHashes,
// }) async {
// try {
// Logging.instance.log(
// "attempting to fetch spark.getsparkmintmetadata...",
// level: LogLevel.Info,
// );
// await checkElectrumAdapter();
// final List<dynamic> response =
// await (getElectrumAdapter() as FiroElectrumClient)
// .getSparkMintMetaData(sparkCoinHashes: sparkCoinHashes);
// Logging.instance.log(
// "Fetching spark.getsparkmintmetadata finished",
// level: LogLevel.Info,
// );
// return List<Map<String, dynamic>>.from(response);
// } catch (e, s) {
// Logging.instance.log(e, level: LogLevel.Error);
// rethrow;
// }
// }
/// Returns the latest Spark set id
///
@ -1017,20 +1057,22 @@ class ElectrumXClient {
String? requestID,
}) async {
try {
Logging.instance.log(
Logging.instance.d(
"attempting to fetch spark.getsparklatestcoinid...",
level: LogLevel.Info,
);
await checkElectrumAdapter();
final int response = await (getElectrumAdapter() as FiroElectrumClient)
.getSparkLatestCoinId();
Logging.instance.log(
Logging.instance.d(
"Fetching spark.getsparklatestcoinid finished",
level: LogLevel.Info,
);
return response;
} catch (e) {
Logging.instance.log(e, level: LogLevel.Error);
} catch (e, s) {
Logging.instance.e(
e,
error: e,
stackTrace: s,
);
rethrow;
}
}
@ -1050,15 +1092,18 @@ class ElectrumXClient {
.map((e) => e.toHexReversedFromBase64)
.toSet();
Logging.instance.log(
Logging.instance.d(
"Finished ElectrumXClient.getMempoolTxids(). "
"Duration=${DateTime.now().difference(start)}",
level: LogLevel.Info,
);
return txids;
} catch (e) {
Logging.instance.log(e, level: LogLevel.Error);
} catch (e, s) {
Logging.instance.e(
e,
error: e,
stackTrace: s,
);
rethrow;
}
}
@ -1084,7 +1129,7 @@ class ElectrumXClient {
final List<SparkMempoolData> result = [];
for (final entry in map.entries) {
result.add(
(
SparkMempoolData(
txid: entry.key,
serialContext:
List<String>.from(entry.value["serial_context"] as List),
@ -1095,15 +1140,14 @@ class ElectrumXClient {
);
}
Logging.instance.log(
Logging.instance.d(
"Finished ElectrumXClient.getMempoolSparkData(txids: $txids). "
"Duration=${DateTime.now().difference(start)}",
level: LogLevel.Info,
);
return result;
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Error);
Logging.instance.e("$e\n$s", error: e, stackTrace: s);
rethrow;
}
}
@ -1127,19 +1171,119 @@ class ElectrumXClient {
final map = Map<String, dynamic>.from(response as Map);
final tags = List<List<dynamic>>.from(map["tagsandtxids"] as List);
Logging.instance.log(
Logging.instance.d(
"Finished ElectrumXClient.getSparkUnhashedUsedCoinsTagsWithTxHashes("
"startNumber=$startNumber). # of tags fetched=${tags.length}, "
"Duration=${DateTime.now().difference(start)}",
level: LogLevel.Info,
);
return tags;
} catch (e) {
Logging.instance.log(e, level: LogLevel.Error);
} catch (e, s) {
Logging.instance.e(
e,
error: e,
stackTrace: s,
);
rethrow;
}
}
// ======== New Paginated Endpoints ==========================================
Future<SparkAnonymitySetMeta> getSparkAnonymitySetMeta({
String? requestID,
required int coinGroupId,
}) async {
try {
const command = "spark.getsparkanonymitysetmeta";
Logging.instance.d(
"[${getElectrumAdapter()?.host}] => attempting to fetch $command...",
);
final start = DateTime.now();
final response = await request(
requestID: requestID,
command: command,
args: [
"$coinGroupId",
],
);
final map = Map<String, dynamic>.from(response as Map);
final result = SparkAnonymitySetMeta(
coinGroupId: coinGroupId,
blockHash: map["blockHash"] as String,
setHash: map["setHash"] as String,
size: map["size"] as int,
);
Logging.instance.d(
"Finished ElectrumXClient.getSparkAnonymitySetMeta("
"requestID=$requestID, "
"coinGroupId=$coinGroupId"
"). Set meta=$result, "
"Duration=${DateTime.now().difference(start)}",
);
return result;
} catch (e, s) {
Logging.instance.e(
e,
error: e,
stackTrace: s,
);
rethrow;
}
}
Future<List<dynamic>> getSparkAnonymitySetBySector({
String? requestID,
required int coinGroupId,
required String latestBlock,
required int startIndex, // inclusive
required int endIndex, // exclusive
}) async {
try {
const command =
"spark.getsparkanonymitysetsector"; // TODO verify this will be correct
final start = DateTime.now();
final response = await request(
requestID: requestID,
command: command,
args: [
"$coinGroupId",
latestBlock,
"$startIndex",
"$endIndex",
],
);
final map = Map<String, dynamic>.from(response as Map);
final result = map["coins"] as List;
Logging.instance.d(
"Finished ElectrumXClient.getSparkAnonymitySetBySector("
"requestID=$requestID, "
"coinGroupId=$coinGroupId, "
"latestBlock=$latestBlock, "
"startIndex=$startIndex, "
"endIndex=$endIndex"
"). # of coins=${result.length}, "
"Duration=${DateTime.now().difference(start)}",
);
return result;
} catch (e, s) {
Logging.instance.e(
e,
error: e,
stackTrace: s,
);
rethrow;
}
}
// ===========================================================================
Future<bool> isMasterNodeCollateral({
@ -1158,16 +1302,19 @@ class ElectrumXClient {
],
);
Logging.instance.log(
Logging.instance.d(
"Finished ElectrumXClient.isMasterNodeCollateral, "
"response: $response, "
"Duration=${DateTime.now().difference(start)}",
level: LogLevel.Info,
);
return response as bool;
} catch (e) {
Logging.instance.log(e, level: LogLevel.Error);
} catch (e, s) {
Logging.instance.e(
e,
error: e,
stackTrace: s,
);
rethrow;
}
}
@ -1226,7 +1373,7 @@ class ElectrumXClient {
} catch (e, s) {
final String msg = "Error parsing fee rate. Response: $response"
"\nResult: $response\nError: $e\nStack trace: $s";
Logging.instance.log(msg, level: LogLevel.Fatal);
Logging.instance.e(msg, error: e, stackTrace: s);
throw Exception(msg);
}
} catch (e) {

View file

@ -503,7 +503,7 @@
// _responseHandler(response);
// } catch (e, s) {
// Logging.instance
// .log("JsonRPC jsonDecode: $e\n$s", level: LogLevel.Error);
// .log("JsonRPC jsonDecode", error: e, stackTrace: s,);
// rethrow;
// } finally {
// _responseData = [];

View file

@ -0,0 +1,8 @@
class NodeTorMismatchConfigException implements Exception {
final String message;
NodeTorMismatchConfigException({required this.message});
@override
String toString() => message;
}

View file

@ -13,22 +13,21 @@ import 'dart:io';
import 'dart:math';
import 'package:coinlib_flutter/coinlib_flutter.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:compat/compat.dart' as lib_monero_compat;
import 'package:cs_monero/cs_monero.dart' as lib_monero;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/wownero/wownero.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:isar/isar.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:window_size/window_size.dart';
import 'package:xelis_flutter/src/api/api.dart' as xelis_api;
import 'package:xelis_flutter/src/api/logger.dart' as xelis_logging;
import 'package:xelis_flutter/src/frb_generated.dart' as xelis_rust;
import 'app_config.dart';
import 'db/db_version_migration.dart';
@ -39,7 +38,6 @@ import 'db/sqlite/firo_cache.dart';
import 'models/exchange/change_now/exchange_transaction.dart';
import 'models/exchange/change_now/exchange_transaction_status.dart';
import 'models/exchange/response_objects/trade.dart';
import 'models/isar/models/isar_models.dart';
import 'models/models.dart';
import 'models/node_model.dart';
import 'models/notification_model.dart';
@ -60,8 +58,6 @@ import 'providers/global/base_currencies_provider.dart';
import 'providers/global/trades_service_provider.dart';
import 'providers/providers.dart';
import 'route_generator.dart';
// import 'package:stackwallet/services/buy/buy_data_loading_service.dart';
import 'services/debug_service.dart';
import 'services/exchange/exchange_data_loading_service.dart';
import 'services/locale_service.dart';
import 'services/node_service.dart';
@ -79,27 +75,53 @@ import 'utilities/prefs.dart';
import 'utilities/stack_file_system.dart';
import 'utilities/util.dart';
import 'wallets/isar/providers/all_wallets_info_provider.dart';
import 'wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
import 'widgets/crypto_notifications.dart';
final openedFromSWBFileStringStateProvider =
StateProvider<String?>((ref) => null);
final openedFromSWBFileStringStateProvider = StateProvider<String?>(
(ref) => null,
);
void startListeningToRustLogs() {
xelis_api.createLogStream().listen(
(logEntry) {
final Level level;
switch (logEntry.level) {
case xelis_logging.Level.error:
level = Level.error;
case xelis_logging.Level.warn:
level = Level.warning;
case xelis_logging.Level.info:
level = Level.info;
case xelis_logging.Level.debug:
level = Level.debug;
case xelis_logging.Level.trace:
level = Level.trace;
}
Logging.instance.log(
level,
"[Xelis Rust Log] ${logEntry.tag}: ${logEntry.msg}",
);
},
onError: (dynamic e) {
Logging.instance.e("Error receiving Xelis Rust logs: $e");
},
);
}
// main() is the entry point to the app. It initializes Hive (local database),
// runs the MyApp widget and checks for new users, caching the value in the
// miscellaneous box for later use
void main(List<String> args) async {
// talker.info('initializing Rust lib ...');
await xelis_rust.RustLib.init();
WidgetsFlutterBinding.ensureInitialized();
if (Util.isDesktop && args.length == 2 && args.first == "-d") {
StackFileSystem.setDesktopOverrideDir(args.last);
}
// Tell flutter_libmonero how to get access to the application dir
FS.setApplicationRootDirectoryFunction(
StackFileSystem.applicationRootDirectory,
);
// TODO set any other external libs file paths (bad external lib design workaround)
final loadCoinlibFuture = loadCoinlib();
GoogleFonts.config.allowRuntimeFetching = false;
@ -121,26 +143,11 @@ void main(List<String> args) async {
if (screenHeight != null) {
// starting to height be 3/4 screen height or 900, whichever is smaller
final height = min<double>(screenHeight * 0.75, 900);
setWindowFrame(
Rect.fromLTWH(0, 0, 1220, height),
);
setWindowFrame(Rect.fromLTWH(0, 0, 1220, height));
}
}
// FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
if (!(Logging.isArmLinux || Logging.isTestEnv)) {
final isar = await Isar.open(
[LogSchema],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
inspector: false,
maxSizeMiB: 512,
);
await Logging.instance.init(isar);
await DebugService.instance.init(isar);
// clear out all info logs on startup. No need to await and block
unawaited(DebugService.instance.deleteLogsOlderThan());
}
// Registering Transaction Model Adapters
DB.instance.hive.registerAdapter(TransactionDataAdapter());
@ -172,15 +179,15 @@ void main(List<String> args) async {
// node model adapter
DB.instance.hive.registerAdapter(NodeModelAdapter());
DB.instance.hive.registerAdapter(NodeAdapter());
if (!DB.instance.hive.isAdapterRegistered(WalletInfoAdapter().typeId)) {
DB.instance.hive.registerAdapter(WalletInfoAdapter());
if (!DB.instance.hive.isAdapterRegistered(
lib_monero_compat.WalletInfoAdapter().typeId,
)) {
DB.instance.hive.registerAdapter(lib_monero_compat.WalletInfoAdapter());
}
DB.instance.hive.registerAdapter(WalletTypeAdapter());
DB.instance.hive.registerAdapter(lib_monero_compat.WalletTypeAdapter());
DB.instance.hive.registerAdapter(UnspentCoinsInfoAdapter());
lib_monero.Logging.useLogger = kDebugMode;
DB.instance.hive.init(
(await StackFileSystem.applicationHiveDirectory()).path,
@ -190,6 +197,17 @@ void main(List<String> args) async {
await DB.instance.hive.openBox<dynamic>(DB.boxNamePrefs);
await Prefs.instance.init();
await Logging.instance.initialize(
(await StackFileSystem.applicationLogsDirectory(Prefs.instance)).path,
level: Prefs.instance.logLevel,
);
await xelis_api.setUpRustLogger();
startListeningToRustLogs();
// setup lib spark logging
initSparkLogging(Prefs.instance.logLevel);
if (AppConfig.appName == "Campfire" &&
!Util.isDesktop &&
!CampfireMigration.didRun) {
@ -213,10 +231,12 @@ void main(List<String> args) async {
// Desktop migrate handled elsewhere (currently desktop_login_view.dart)
if (!Util.isDesktop) {
final int dbVersion = DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
) as int? ??
final int dbVersion =
DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
)
as int? ??
0;
if (dbVersion < Constants.currentDataVersion) {
try {
@ -228,21 +248,18 @@ void main(List<String> args) async {
),
);
} catch (e, s) {
Logging.instance.log(
"Cannot migrate mobile database\n$e $s",
level: LogLevel.Error,
printFullLength: true,
Logging.instance.w(
"Cannot migrate mobile database",
error: e,
stackTrace: s,
);
}
}
}
monero.onStartup();
wownero.onStartup();
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
// overlays: [SystemUiOverlay.bottom]);
await NotificationApi.init();
unawaited(NotificationApi.init());
await loadCoinlibFuture;
@ -254,22 +271,25 @@ void main(List<String> args) async {
// verify current user preference theme and revert to default
// if problems are found to prevent app being unusable
if (!(await ThemeService.instance
.verifyInstalled(themeId: Prefs.instance.themeId))) {
if (!(await ThemeService.instance.verifyInstalled(
themeId: Prefs.instance.themeId,
))) {
Prefs.instance.themeId = "light";
}
// verify current user preference light brightness theme and revert to default
// if problems are found to prevent app being unusable
if (!(await ThemeService.instance
.verifyInstalled(themeId: Prefs.instance.systemBrightnessLightThemeId))) {
if (!(await ThemeService.instance.verifyInstalled(
themeId: Prefs.instance.systemBrightnessLightThemeId,
))) {
Prefs.instance.systemBrightnessLightThemeId = "light";
}
// verify current user preference dark brightness theme and revert to default
// if problems are found to prevent app being unusable
if (!(await ThemeService.instance
.verifyInstalled(themeId: Prefs.instance.systemBrightnessDarkThemeId))) {
if (!(await ThemeService.instance.verifyInstalled(
themeId: Prefs.instance.systemBrightnessDarkThemeId,
))) {
Prefs.instance.systemBrightnessDarkThemeId = "dark";
}
@ -285,18 +305,14 @@ class MyApp extends StatelessWidget {
final localeService = LocaleService();
localeService.loadLocale();
return const KeyboardDismisser(
child: MaterialAppWithTheme(),
);
return const KeyboardDismisser(child: MaterialAppWithTheme());
}
}
// Sidenote: MaterialAppWithTheme and InitView are only separated for clarity. No other reason.
class MaterialAppWithTheme extends ConsumerStatefulWidget {
const MaterialAppWithTheme({
super.key,
});
const MaterialAppWithTheme({super.key});
@override
ConsumerState<MaterialAppWithTheme> createState() =>
@ -370,7 +386,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
prefs: ref.read(prefsChangeNotifierProvider),
);
ref.read(priceAnd24hChangeNotifierProvider).start(true);
await ref.read(pWallets).load(
await ref
.read(pWallets)
.load(
ref.read(prefsChangeNotifierProvider),
ref.read(mainDBProvider),
);
@ -378,7 +396,8 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
// TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet
// unawaited(_nodeService.updateCommunityNodes());
if (AppConfig.hasFeature(AppFeature.swap)) {
if (AppConfig.hasFeature(AppFeature.swap) &&
ref.read(prefsChangeNotifierProvider).enableExchange) {
await ExchangeDataLoadingService.instance.initDB();
// run without awaiting
if (ref.read(prefsChangeNotifierProvider).externalCalls &&
@ -399,7 +418,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
if (ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled) {
switch (ref.read(prefsChangeNotifierProvider).backupFrequencyType) {
case BackupFrequencyType.everyTenMinutes:
ref.read(autoSWBServiceProvider).startPeriodicBackupTimer(
ref
.read(autoSWBServiceProvider)
.startPeriodicBackupTimer(
duration: const Duration(minutes: 10),
);
break;
@ -417,7 +438,7 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
// .userID; // Just reading the ref should set it if it's not already set
// We shouldn't need to do this, instead only generating an ID when (or if) the userID is looked up when creating a quote
} catch (e, s) {
Logger.print("$e $s", normalLength: false);
Logging.instance.e("load failure", error: e, stackTrace: s);
}
}
@ -432,9 +453,10 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
ref.read(prefsChangeNotifierProvider).systemBrightnessDarkThemeId;
break;
case Brightness.light:
themeId = ref
.read(prefsChangeNotifierProvider)
.systemBrightnessLightThemeId;
themeId =
ref
.read(prefsChangeNotifierProvider)
.systemBrightnessLightThemeId;
break;
}
} else {
@ -453,9 +475,8 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
ref.read(applicationThemesDirectoryPathProvider.notifier).state =
StackFileSystem.themesDir!.path;
ref.read(themeProvider.state).state = ref.read(pThemeService).getTheme(
themeId: themeId,
)!;
ref.read(themeProvider.state).state =
ref.read(pThemeService).getTheme(themeId: themeId)!;
if (Platform.isAndroid) {
// fetch open file if it exists
@ -483,18 +504,17 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
ref.read(prefsChangeNotifierProvider).systemBrightnessDarkThemeId;
break;
case Brightness.light:
themeId = ref
.read(prefsChangeNotifierProvider)
.systemBrightnessLightThemeId;
themeId =
ref
.read(prefsChangeNotifierProvider)
.systemBrightnessLightThemeId;
break;
}
WidgetsBinding.instance.addPostFrameCallback((_) {
if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) {
ref.read(themeProvider.state).state =
ref.read(pThemeService).getTheme(
themeId: themeId,
)!;
ref.read(pThemeService).getTheme(themeId: themeId)!;
}
});
};
@ -573,15 +593,14 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
/// should only be called on android currently
Future<void> getOpenFile() async {
// update provider with new file content state
ref.read(openedFromSWBFileStringStateProvider.state).state =
await platform.invokeMethod("getOpenFile");
ref.read(openedFromSWBFileStringStateProvider.state).state = await platform
.invokeMethod("getOpenFile");
// call reset to clear cached value
await resetOpenPath();
Logging.instance.log(
Logging.instance.d(
"This is the .swb content from intent: ${ref.read(openedFromSWBFileStringStateProvider.state).state}",
level: LogLevel.Info,
);
}
@ -592,9 +611,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
Future<void> goToRestoreSWB(String encrypted) async {
if (!ref.read(prefsChangeNotifierProvider).hasPin) {
await Navigator.of(navigatorKey.currentContext!)
.pushNamed(CreatePinView.routeName, arguments: true)
.then((value) {
await Navigator.of(
navigatorKey.currentContext!,
).pushNamed(CreatePinView.routeName, arguments: true).then((value) {
if (value is! bool || value == false) {
Navigator.of(navigatorKey.currentContext!).pushNamed(
RestoreFromEncryptedStringView.routeName,
@ -608,16 +627,17 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
navigatorKey.currentContext!,
RouteGenerator.getRoute(
shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
builder: (_) => LockscreenView(
showBackButton: true,
routeOnSuccess: RestoreFromEncryptedStringView.routeName,
routeOnSuccessArguments: encrypted,
biometricsCancelButtonString: "CANCEL",
biometricsLocalizedReason:
"Authenticate to restore ${AppConfig.appName} backup",
biometricsAuthenticationTitle:
"Restore ${AppConfig.prefix} backup",
),
builder:
(_) => LockscreenView(
showBackButton: true,
routeOnSuccess: RestoreFromEncryptedStringView.routeName,
routeOnSuccessArguments: encrypted,
biometricsCancelButtonString: "CANCEL",
biometricsLocalizedReason:
"Authenticate to restore ${AppConfig.appName} backup",
biometricsAuthenticationTitle:
"Restore ${AppConfig.prefix} backup",
),
settings: const RouteSettings(name: "/swbrestorelockscreen"),
),
),
@ -627,10 +647,7 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
InputBorder _buildOutlineInputBorder(Color color) {
return OutlineInputBorder(
borderSide: BorderSide(
width: 1,
color: color,
),
borderSide: BorderSide(width: 1, color: color),
borderRadius: BorderRadius.circular(Constants.size.circularBorderRadius),
);
}
@ -668,9 +685,7 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
),
// splashFactory: NoSplash.splashFactory,
splashColor: Colors.transparent,
buttonTheme: ButtonThemeData(
splashColor: colorScheme.splash,
),
buttonTheme: ButtonThemeData(splashColor: colorScheme.splash),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
// splashFactory: NoSplash.splashFactory,
@ -678,8 +693,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
minimumSize: MaterialStateProperty.all<Size>(const Size(46, 46)),
// textStyle: MaterialStateProperty.all<TextStyle>(
// STextStyles.button(context)),
foregroundColor:
MaterialStateProperty.all(colorScheme.buttonTextSecondary),
foregroundColor: MaterialStateProperty.all(
colorScheme.buttonTextSecondary,
),
backgroundColor: MaterialStateProperty.all<Color>(
colorScheme.buttonBackSecondary,
),
@ -696,25 +712,22 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
checkboxTheme: CheckboxThemeData(
splashRadius: 0,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(Constants.size.checkboxBorderRadius),
borderRadius: BorderRadius.circular(
Constants.size.checkboxBorderRadius,
),
),
checkColor: MaterialStateColor.resolveWith(
(state) {
if (state.contains(MaterialState.selected)) {
return colorScheme.checkboxIconChecked;
}
checkColor: MaterialStateColor.resolveWith((state) {
if (state.contains(MaterialState.selected)) {
return colorScheme.checkboxIconChecked;
}
return colorScheme.checkboxBGChecked;
}),
fillColor: MaterialStateColor.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return colorScheme.checkboxBGChecked;
},
),
fillColor: MaterialStateColor.resolveWith(
(states) {
if (states.contains(MaterialState.selected)) {
return colorScheme.checkboxBGChecked;
}
return colorScheme.checkboxBorderEmpty;
},
),
}
return colorScheme.checkboxBorderEmpty;
}),
),
appBarTheme: AppBarTheme(
centerTitle: false,
@ -732,91 +745,101 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
),
// labelStyle: STextStyles.fieldLabel(context),
// hintStyle: STextStyles.fieldLabel(context),
enabledBorder:
_buildOutlineInputBorder(colorScheme.textFieldDefaultBG),
focusedBorder:
_buildOutlineInputBorder(colorScheme.textFieldDefaultBG),
enabledBorder: _buildOutlineInputBorder(
colorScheme.textFieldDefaultBG,
),
focusedBorder: _buildOutlineInputBorder(
colorScheme.textFieldDefaultBG,
),
errorBorder: _buildOutlineInputBorder(colorScheme.textFieldDefaultBG),
disabledBorder:
_buildOutlineInputBorder(colorScheme.textFieldDefaultBG),
focusedErrorBorder:
_buildOutlineInputBorder(colorScheme.textFieldDefaultBG),
disabledBorder: _buildOutlineInputBorder(
colorScheme.textFieldDefaultBG,
),
focusedErrorBorder: _buildOutlineInputBorder(
colorScheme.textFieldDefaultBG,
),
),
),
home: CryptoNotifications(
child: Util.isDesktop
? FutureBuilder(
future: loadShared(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (_desktopHasPassword) {
String? startupWalletId;
if (ref
.read(prefsChangeNotifierProvider)
.gotoWalletOnStartup) {
startupWalletId = ref
child:
Util.isDesktop
? FutureBuilder(
future: loadShared(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (_desktopHasPassword) {
String? startupWalletId;
if (ref
.read(prefsChangeNotifierProvider)
.startupWalletId;
}
.gotoWalletOnStartup) {
startupWalletId =
ref
.read(prefsChangeNotifierProvider)
.startupWalletId;
}
return DesktopLoginView(
startupWalletId: startupWalletId,
load: load,
);
} else {
return const IntroView();
}
} else {
return const LoadingView();
}
},
)
: FutureBuilder(
future: load(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// FlutterNativeSplash.remove();
if (ref.read(pAllWalletsInfo).isNotEmpty ||
ref.read(prefsChangeNotifierProvider).hasPin) {
// return HomeView();
String? startupWalletId;
if (ref
.read(prefsChangeNotifierProvider)
.gotoWalletOnStartup) {
startupWalletId = ref
.read(prefsChangeNotifierProvider)
.startupWalletId;
}
return LockscreenView(
isInitialAppLogin: true,
routeOnSuccess: HomeView.routeName,
routeOnSuccessArguments: startupWalletId,
biometricsAuthenticationTitle:
"Unlock ${AppConfig.prefix}",
biometricsLocalizedReason:
"Unlock your ${AppConfig.appName} using biometrics",
biometricsCancelButtonString: "Cancel",
);
} else {
if (AppConfig.appName == "Campfire" &&
!CampfireMigration.didRun &&
CampfireMigration.hasOldWallets) {
return const CampfireMigrateView();
return DesktopLoginView(
startupWalletId: startupWalletId,
load: load,
);
} else {
return const IntroView();
}
} else {
return const LoadingView();
}
} else {
// CURRENTLY DISABLED as cannot be animated
// technically not needed as FlutterNativeSplash will overlay
// anything returned here until the future completes but
// FutureBuilder requires you to return something
return const LoadingView();
}
},
),
},
)
: FutureBuilder(
future: load(),
builder: (
BuildContext context,
AsyncSnapshot<void> snapshot,
) {
if (snapshot.connectionState == ConnectionState.done) {
// FlutterNativeSplash.remove();
if (ref.read(pAllWalletsInfo).isNotEmpty ||
ref.read(prefsChangeNotifierProvider).hasPin) {
// return HomeView();
String? startupWalletId;
if (ref
.read(prefsChangeNotifierProvider)
.gotoWalletOnStartup) {
startupWalletId =
ref
.read(prefsChangeNotifierProvider)
.startupWalletId;
}
return LockscreenView(
isInitialAppLogin: true,
routeOnSuccess: HomeView.routeName,
routeOnSuccessArguments: startupWalletId,
biometricsAuthenticationTitle:
"Unlock ${AppConfig.prefix}",
biometricsLocalizedReason:
"Unlock your ${AppConfig.appName} using biometrics",
biometricsCancelButtonString: "Cancel",
);
} else {
if (AppConfig.appName == "Campfire" &&
!CampfireMigration.didRun &&
CampfireMigration.hasOldWallets) {
return const CampfireMigrateView();
} else {
return const IntroView();
}
}
} else {
// CURRENTLY DISABLED as cannot be animated
// technically not needed as FlutterNativeSplash will overlay
// anything returned here until the future completes but
// FutureBuilder requires you to return something
return const LoadingView();
}
},
),
),
);
}

View file

@ -0,0 +1,98 @@
class SparkMempoolData {
final String txid;
final List<String> serialContext;
final List<String> lTags;
final List<String> coins;
SparkMempoolData({
required this.txid,
required this.serialContext,
required this.lTags,
required this.coins,
});
@override
String toString() {
return "SparkMempoolData{"
"txid: $txid, "
"serialContext: $serialContext, "
"lTags: $lTags, "
"coins: $coins"
"}";
}
}
class SparkAnonymitySetMeta {
final int coinGroupId;
final String blockHash;
final String setHash;
final int size;
SparkAnonymitySetMeta({
required this.coinGroupId,
required this.blockHash,
required this.setHash,
required this.size,
});
@override
String toString() {
return "SparkAnonymitySetMeta{"
"coinGroupId: $coinGroupId, "
"blockHash: $blockHash, "
"setHash: $setHash, "
"size: $size"
"}";
}
}
class RawSparkCoin {
final String serialized;
final String txHash;
final String context;
final int groupId;
RawSparkCoin({
required this.serialized,
required this.txHash,
required this.context,
required this.groupId,
});
static RawSparkCoin fromRPCResponse(List<dynamic> data, int groupId) {
try {
if (data.length != 3) throw Exception();
return RawSparkCoin(
serialized: data[0] as String,
txHash: data[1] as String,
context: data[2] as String,
groupId: groupId,
);
} catch (_) {
throw Exception("Invalid coin data: $data");
}
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is! RawSparkCoin) return false;
return serialized == other.serialized &&
txHash == other.txHash &&
groupId == other.groupId &&
context == other.context;
}
@override
int get hashCode => Object.hash(serialized, txHash, context);
@override
String toString() {
return "SparkAnonymitySetMeta{"
"serialized: $serialized, "
"txHash: $txHash, "
"context: $context, "
"groupId: $groupId"
"}";
}
}

View file

@ -9,6 +9,7 @@
*/
import 'package:decimal/decimal.dart';
import '../../../utilities/logger.dart';
enum CNEstimateType { direct, reverse }
@ -112,8 +113,11 @@ class CNExchangeEstimate {
toAmount: Decimal.parse(json["toAmount"].toString()),
);
} catch (e, s) {
Logging.instance
.log("Failed to parse: $json \n$e\n$s", level: LogLevel.Fatal);
Logging.instance.e(
"Failed to parse: $json",
error: e,
stackTrace: s,
);
rethrow;
}
}

View file

@ -57,8 +57,11 @@ class EstimatedExchangeAmount {
networkFee: Decimal.tryParse(json["networkFee"].toString()),
);
} catch (e, s) {
Logging.instance
.log("Failed to parse: $json \n$e\n$s", level: LogLevel.Fatal);
Logging.instance.e(
"Failed to parse: $json",
error: e,
stackTrace: s,
);
rethrow;
}
}

View file

@ -187,7 +187,7 @@ class ExchangeTransactionStatus {
});
factory ExchangeTransactionStatus.fromJson(Map<String, dynamic> json) {
Logging.instance.log(json, printFullLength: true, level: LogLevel.Info);
Logging.instance.d(json, stackTrace: StackTrace.current);
try {
return ExchangeTransactionStatus(
status: changeNowTransactionStatusFromStringIgnoreCase(
@ -228,7 +228,7 @@ class ExchangeTransactionStatus {
payload: json["payload"] as Object?,
);
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Fatal);
Logging.instance.f("", error: e, stackTrace: s);
rethrow;
}
}

View file

@ -9,6 +9,7 @@
*/
import 'package:decimal/decimal.dart';
import '../../../utilities/logger.dart';
class Estimate {
@ -18,6 +19,7 @@ class Estimate {
final String? warningMessage;
final String? rateId;
final String exchangeProvider;
final String? exchangeProviderLogo;
final String? kycRating;
Estimate({
@ -27,6 +29,7 @@ class Estimate {
this.warningMessage,
this.rateId,
required this.exchangeProvider,
this.exchangeProviderLogo,
this.kycRating,
});
@ -46,7 +49,11 @@ class Estimate {
kycRating: kycRating,
);
} catch (e, s) {
Logging.instance.log("Estimate.fromMap(): $e\n$s", level: LogLevel.Error);
Logging.instance.e(
"Estimate.fromMap()",
error: e,
stackTrace: s,
);
rethrow;
}
}

View file

@ -9,6 +9,7 @@
*/
import 'package:decimal/decimal.dart';
import '../../../utilities/logger.dart';
class FixedRateMarket {
@ -53,10 +54,7 @@ class FixedRateMarket {
minerFee: Decimal.tryParse(json["minerFee"].toString()),
);
} catch (e, s) {
Logging.instance.log(
"FixedRateMarket.fromMap(): $e\n$s",
level: LogLevel.Error,
);
Logging.instance.e("FixedRateMarket.fromMap(): ", error: e, stackTrace: s);
rethrow;
}
}

View file

@ -59,10 +59,7 @@ class SPCurrency {
warningsTo: json["warnings_to"] as List<dynamic>,
);
} catch (e, s) {
Logging.instance.log(
"SPCurrency.fromJson failed to parse: $e\n$s",
level: LogLevel.Error,
);
Logging.instance.e("SPCurrency.fromJson failed to parse: ", error: e, stackTrace: s);
rethrow;
}
}

View file

@ -7,7 +7,7 @@ part of 'currency.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetCurrencyCollection on Isar {
IsarCollection<Currency> get currencies => this.collection();
@ -135,7 +135,7 @@ const CurrencySchema = CollectionSchema(
getId: _currencyGetId,
getLinks: _currencyGetLinks,
attach: _currencyAttach,
version: '3.0.5',
version: '3.1.8',
);
int _currencyEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'pair.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetPairCollection on Isar {
IsarCollection<Pair> get pairs => this.collection();
@ -92,7 +92,7 @@ const PairSchema = CollectionSchema(
getId: _pairGetId,
getLinks: _pairGetLinks,
attach: _pairAttach,
version: '3.0.5',
version: '3.1.8',
);
int _pairEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'address_label.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetAddressLabelCollection on Isar {
IsarCollection<AddressLabel> get addressLabels => this.collection();
@ -81,7 +81,7 @@ const AddressLabelSchema = CollectionSchema(
getId: _addressLabelGetId,
getLinks: _addressLabelGetLinks,
attach: _addressLabelAttach,
version: '3.0.5',
version: '3.1.8',
);
int _addressLabelEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'block_explorer.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetTransactionBlockExplorerCollection on Isar {
IsarCollection<TransactionBlockExplorer> get transactionBlockExplorers =>
@ -54,7 +54,7 @@ const TransactionBlockExplorerSchema = CollectionSchema(
getId: _transactionBlockExplorerGetId,
getLinks: _transactionBlockExplorerGetLinks,
attach: _transactionBlockExplorerAttach,
version: '3.0.5',
version: '3.1.8',
);
int _transactionBlockExplorerEstimateSize(

View file

@ -11,6 +11,7 @@
import 'dart:convert';
import 'package:isar/isar.dart';
import '../../../../exceptions/address/address_exception.dart';
import 'crypto_currency_address.dart';
import 'transaction.dart';
@ -27,6 +28,7 @@ class Address extends CryptoCurrencyAddress {
required this.derivationPath,
required this.type,
required this.subType,
this.zSafeFrost,
this.otherData,
});
@ -55,6 +57,8 @@ class Address extends CryptoCurrencyAddress {
final transactions = IsarLinks<Transaction>();
late final bool? zSafeFrost;
int derivationChain() {
if (subType == AddressSubType.receiving) {
return 0; // 0 for receiving (external)
@ -80,6 +84,7 @@ class Address extends CryptoCurrencyAddress {
AddressType? type,
AddressSubType? subType,
DerivationPath? derivationPath,
bool? zSafeFrost,
String? otherData,
}) {
return Address(
@ -90,6 +95,7 @@ class Address extends CryptoCurrencyAddress {
type: type ?? this.type,
subType: subType ?? this.subType,
derivationPath: derivationPath ?? this.derivationPath,
zSafeFrost: zSafeFrost ?? this.zSafeFrost,
otherData: otherData ?? this.otherData,
);
}
@ -105,6 +111,7 @@ class Address extends CryptoCurrencyAddress {
"subType: ${subType.name}, "
"transactionsLength: ${transactions.length} "
"derivationPath: $derivationPath, "
"zSafeFrost: $zSafeFrost, "
"otherData: $otherData, "
"}";
@ -117,6 +124,7 @@ class Address extends CryptoCurrencyAddress {
"type": type.name,
"subType": subType.name,
"derivationPath": derivationPath?.value,
"zSafeFrost": zSafeFrost,
"otherData": otherData,
};
return jsonEncode(result);
@ -143,6 +151,7 @@ class Address extends CryptoCurrencyAddress {
derivationPath: derivationPath,
type: AddressType.values.byName(json["type"] as String),
subType: AddressSubType.values.byName(json["subType"] as String),
zSafeFrost: json["zSafeFrost"] as bool?,
otherData: json["otherData"] as String?,
);
}
@ -165,7 +174,9 @@ enum AddressType {
tezos,
frostMS,
p2tr,
solana;
solana,
cardanoShelley,
xelis;
String get readableName {
switch (this) {
@ -201,6 +212,10 @@ enum AddressType {
return "Solana";
case AddressType.p2tr:
return "P2TR (taproot)";
case AddressType.cardanoShelley:
return "Cardano Shelley";
case AddressType.xelis:
return "Xelis";
}
}
}

View file

@ -7,7 +7,7 @@ part of 'address.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetAddressCollection on Isar {
IsarCollection<Address> get addresses => this.collection();
@ -59,6 +59,11 @@ const AddressSchema = CollectionSchema(
id: 7,
name: r'walletId',
type: IsarType.string,
),
r'zSafeFrost': PropertySchema(
id: 8,
name: r'zSafeFrost',
type: IsarType.bool,
)
},
estimateSize: _addressEstimateSize,
@ -124,7 +129,7 @@ const AddressSchema = CollectionSchema(
getId: _addressGetId,
getLinks: _addressGetLinks,
attach: _addressAttach,
version: '3.0.5',
version: '3.1.8',
);
int _addressEstimateSize(
@ -172,6 +177,7 @@ void _addressSerialize(
writer.writeByte(offsets[5], object.type.index);
writer.writeString(offsets[6], object.value);
writer.writeString(offsets[7], object.walletId);
writer.writeBool(offsets[8], object.zSafeFrost);
}
Address _addressDeserialize(
@ -195,6 +201,7 @@ Address _addressDeserialize(
AddressType.p2pkh,
value: reader.readString(offsets[6]),
walletId: reader.readString(offsets[7]),
zSafeFrost: reader.readBoolOrNull(offsets[8]),
);
object.id = id;
return object;
@ -229,6 +236,8 @@ P _addressDeserializeProp<P>(
return (reader.readString(offset)) as P;
case 7:
return (reader.readString(offset)) as P;
case 8:
return (reader.readBoolOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
@ -269,6 +278,8 @@ const _AddresstypeEnumValueMap = {
'frostMS': 13,
'p2tr': 14,
'solana': 15,
'cardanoShelley': 16,
'xelis': 17,
};
const _AddresstypeValueEnumMap = {
0: AddressType.p2pkh,
@ -287,6 +298,8 @@ const _AddresstypeValueEnumMap = {
13: AddressType.frostMS,
14: AddressType.p2tr,
15: AddressType.solana,
16: AddressType.cardanoShelley,
17: AddressType.xelis,
};
Id _addressGetId(Address object) {
@ -1474,6 +1487,32 @@ extension AddressQueryFilter
));
});
}
QueryBuilder<Address, Address, QAfterFilterCondition> zSafeFrostIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'zSafeFrost',
));
});
}
QueryBuilder<Address, Address, QAfterFilterCondition> zSafeFrostIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNotNull(
property: r'zSafeFrost',
));
});
}
QueryBuilder<Address, Address, QAfterFilterCondition> zSafeFrostEqualTo(
bool? value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'zSafeFrost',
value: value,
));
});
}
}
extension AddressQueryObject
@ -1621,6 +1660,18 @@ extension AddressQuerySortBy on QueryBuilder<Address, Address, QSortBy> {
return query.addSortBy(r'walletId', Sort.desc);
});
}
QueryBuilder<Address, Address, QAfterSortBy> sortByZSafeFrost() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'zSafeFrost', Sort.asc);
});
}
QueryBuilder<Address, Address, QAfterSortBy> sortByZSafeFrostDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'zSafeFrost', Sort.desc);
});
}
}
extension AddressQuerySortThenBy
@ -1708,6 +1759,18 @@ extension AddressQuerySortThenBy
return query.addSortBy(r'walletId', Sort.desc);
});
}
QueryBuilder<Address, Address, QAfterSortBy> thenByZSafeFrost() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'zSafeFrost', Sort.asc);
});
}
QueryBuilder<Address, Address, QAfterSortBy> thenByZSafeFrostDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'zSafeFrost', Sort.desc);
});
}
}
extension AddressQueryWhereDistinct
@ -1756,6 +1819,12 @@ extension AddressQueryWhereDistinct
return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive);
});
}
QueryBuilder<Address, Address, QDistinct> distinctByZSafeFrost() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'zSafeFrost');
});
}
}
extension AddressQueryProperty
@ -1814,6 +1883,12 @@ extension AddressQueryProperty
return query.addPropertyName(r'walletId');
});
}
QueryBuilder<Address, bool?, QQueryOperations> zSafeFrostProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'zSafeFrost');
});
}
}
// **************************************************************************
@ -1821,7 +1896,7 @@ extension AddressQueryProperty
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const DerivationPathSchema = Schema(
name: r'DerivationPath',

View file

@ -7,7 +7,7 @@ part of 'input.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const InputSchema = Schema(
name: r'Input',

View file

@ -7,7 +7,7 @@ part of 'output.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const OutputSchema = Schema(
name: r'Output',

View file

@ -7,7 +7,7 @@ part of 'transaction.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetTransactionCollection on Isar {
IsarCollection<Transaction> get transactions => this.collection();
@ -171,7 +171,7 @@ const TransactionSchema = CollectionSchema(
getId: _transactionGetId,
getLinks: _transactionGetLinks,
attach: _transactionAttach,
version: '3.0.5',
version: '3.1.8',
);
int _transactionEstimateSize(

View file

@ -8,6 +8,7 @@
*
*/
import 'dart:convert';
import 'dart:math';
import 'package:isar/isar.dart';
@ -76,12 +77,43 @@ class UTXO {
int getConfirmations(int currentChainHeight) {
if (blockTime == null || blockHash == null) return 0;
if (blockHeight == null || blockHeight! <= 0) return 0;
return max(0, currentChainHeight - (blockHeight! - 1));
return _isMonero()
? max(0, currentChainHeight - (blockHeight!))
: max(0, currentChainHeight - (blockHeight! - 1));
}
bool isConfirmed(int currentChainHeight, int minimumConfirms) {
bool isConfirmed(
int currentChainHeight,
int minimumConfirms,
int minimumCoinbaseConfirms, {
int? overrideMinConfirms, // added to handle namecoin name op outputs
}) {
final confirmations = getConfirmations(currentChainHeight);
return confirmations >= minimumConfirms;
if (overrideMinConfirms != null) {
return confirmations >= overrideMinConfirms;
}
return confirmations >=
(isCoinbase ? minimumCoinbaseConfirms : minimumConfirms);
}
// fuzzy
bool _isMonero() {
return keyImage != null;
}
@ignore
String? get keyImage {
if (otherData == null) {
return null;
}
try {
final map = jsonDecode(otherData!) as Map;
return map[UTXOOtherDataKeys.keyImage] as String;
} catch (_) {
return null;
}
}
UTXO copyWith({
@ -149,3 +181,9 @@ class UTXO {
@ignore
int get hashCode => Object.hashAll([walletId, txid, vout]);
}
abstract final class UTXOOtherDataKeys {
static const keyImage = "keyImage";
static const spent = "spent";
static const nameOpData = "nameOpData";
}

View file

@ -7,7 +7,7 @@ part of 'utxo.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetUTXOCollection on Isar {
IsarCollection<UTXO> get utxos => this.collection();
@ -149,7 +149,7 @@ const UTXOSchema = CollectionSchema(
getId: _uTXOGetId,
getLinks: _uTXOGetLinks,
attach: _uTXOAttach,
version: '3.0.5',
version: '3.1.8',
);
int _uTXOEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'input_v2.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const OutpointV2Schema = Schema(
name: r'OutpointV2',
@ -330,7 +330,7 @@ extension OutpointV2QueryObject
on QueryBuilder<OutpointV2, OutpointV2, QFilterCondition> {}
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const InputV2Schema = Schema(
name: r'InputV2',

View file

@ -7,7 +7,7 @@ part of 'output_v2.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const OutputV2Schema = Schema(
name: r'OutputV2',

View file

@ -87,7 +87,10 @@ class TransactionV2 {
);
}
@ignore
int? get size => _getFromOtherData(key: TxV2OdKeys.size) as int?;
@ignore
int? get vSize => _getFromOtherData(key: TxV2OdKeys.vSize) as int?;
bool get isEpiccashTransaction =>
@ -106,12 +109,19 @@ class TransactionV2 {
int getConfirmations(int currentChainHeight) {
if (height == null || height! <= 0) return 0;
return max(0, currentChainHeight - (height! - 1));
return _isMonero()
? max(0, currentChainHeight - (height!))
: max(0, currentChainHeight - (height! - 1));
}
bool isConfirmed(int currentChainHeight, int minimumConfirms) {
bool isConfirmed(
int currentChainHeight,
int minimumConfirms,
int minimumCoinbaseConfirms,
) {
final confirmations = getConfirmations(currentChainHeight);
return confirmations >= minimumConfirms;
return confirmations >=
(isCoinbase() ? minimumCoinbaseConfirms : minimumConfirms);
}
Amount getFee({required int fractionDigits}) {
@ -121,6 +131,10 @@ class TransactionV2 {
return fee;
}
if (isCoinbase()) {
return Amount.zeroWith(fractionDigits: fractionDigits);
}
final inSum =
inputs.map((e) => e.value).reduce((value, element) => value += element);
final outSum = outputs
@ -131,6 +145,14 @@ class TransactionV2 {
}
Amount getAmountReceivedInThisWallet({required int fractionDigits}) {
if (_isMonero()) {
if (type == TransactionType.incoming) {
return _getMoneroAmount()!;
} else {
return Amount.zeroWith(fractionDigits: fractionDigits);
}
}
final outSum = outputs
.where((e) => e.walletOwns)
.fold(BigInt.zero, (p, e) => p + e.value);
@ -148,6 +170,14 @@ class TransactionV2 {
}
Amount getAmountSentFromThisWallet({required int fractionDigits}) {
if (_isMonero()) {
if (type == TransactionType.outgoing) {
return _getMoneroAmount()!;
} else {
return Amount.zeroWith(fractionDigits: fractionDigits);
}
}
final inSum = inputs
.where((e) => e.walletOwns)
.fold(BigInt.zero, (p, e) => p + e.value);
@ -188,18 +218,40 @@ class TransactionV2 {
}
}
Amount? _getMoneroAmount() {
try {
return Amount.fromSerializedJsonString(
_getFromOtherData(key: TxV2OdKeys.moneroAmount) as String,
);
} catch (_) {
return null;
}
}
bool _isMonero() {
final value = _getFromOtherData(key: TxV2OdKeys.isMoneroTransaction);
return value is bool ? value : false;
}
String statusLabel({
required int currentChainHeight,
required int minConfirms,
required int minCoinbaseConfirms,
}) {
String prettyConfirms() => "("
"${getConfirmations(currentChainHeight)}"
"/"
"${(isCoinbase() ? minCoinbaseConfirms : minConfirms)}"
")";
if (subType == TransactionSubType.cashFusion ||
subType == TransactionSubType.mint ||
(subType == TransactionSubType.sparkMint &&
type == TransactionType.sentToSelf)) {
if (isConfirmed(currentChainHeight, minConfirms)) {
if (isConfirmed(currentChainHeight, minConfirms, minCoinbaseConfirms)) {
return "Anonymized";
} else {
return "Anonymizing";
return "Anonymizing ${prettyConfirms()}";
}
}
@ -211,7 +263,7 @@ class TransactionV2 {
if (isCancelled) {
return "Cancelled";
} else if (type == TransactionType.incoming) {
if (isConfirmed(currentChainHeight, minConfirms)) {
if (isConfirmed(currentChainHeight, minConfirms, minCoinbaseConfirms)) {
return "Received";
} else {
if (numberOfMessages == 1) {
@ -219,11 +271,11 @@ class TransactionV2 {
} else if ((numberOfMessages ?? 0) > 1) {
return "Receiving (waiting for confirmations)"; // TODO test if the sender still has to open again after the receiver has 2 messages present, ie. sender->receiver->sender->node (yes) vs. sender->receiver->node (no)
} else {
return "Receiving";
return "Receiving ${prettyConfirms()}";
}
}
} else if (type == TransactionType.outgoing) {
if (isConfirmed(currentChainHeight, minConfirms)) {
if (isConfirmed(currentChainHeight, minConfirms, minCoinbaseConfirms)) {
return "Sent (confirmed)";
} else {
if (numberOfMessages == 1) {
@ -231,7 +283,7 @@ class TransactionV2 {
} else if ((numberOfMessages ?? 0) > 1) {
return "Sending (waiting for confirmations)";
} else {
return "Sending";
return "Sending ${prettyConfirms()}";
}
}
}
@ -241,19 +293,23 @@ class TransactionV2 {
// if (_transaction.isMinting) {
// return "Minting";
// } else
if (isConfirmed(currentChainHeight, minConfirms)) {
if (isConfirmed(currentChainHeight, minConfirms, minCoinbaseConfirms)) {
return "Received";
} else {
return "Receiving";
return "Receiving ${prettyConfirms()}";
}
} else if (type == TransactionType.outgoing) {
if (isConfirmed(currentChainHeight, minConfirms)) {
if (isConfirmed(currentChainHeight, minConfirms, minCoinbaseConfirms)) {
return "Sent";
} else {
return "Sending";
return "Sending ${prettyConfirms()}";
}
} else if (type == TransactionType.sentToSelf) {
return "Sent to self";
if (isConfirmed(currentChainHeight, minConfirms, minCoinbaseConfirms)) {
return "Sent to self";
} else {
return "Sent to self ${prettyConfirms()}";
}
} else {
return type.name;
}
@ -267,6 +323,9 @@ class TransactionV2 {
return map[key];
}
bool isCoinbase() =>
type == TransactionType.incoming && inputs.any((e) => e.coinbase != null);
@override
String toString() {
return 'TransactionV2(\n'
@ -297,4 +356,7 @@ abstract final class TxV2OdKeys {
static const contractAddress = "contractAddress";
static const nonce = "nonce";
static const overrideFee = "overrideFee";
static const moneroAmount = "moneroAmount";
static const moneroAccountIndex = "moneroAccountIndex";
static const isMoneroTransaction = "isMoneroTransaction";
}

View file

@ -7,7 +7,7 @@ part of 'transaction_v2.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetTransactionV2Collection on Isar {
IsarCollection<TransactionV2> get transactionV2s => this.collection();
@ -177,7 +177,7 @@ const TransactionV2Schema = CollectionSchema(
getId: _transactionV2GetId,
getLinks: _transactionV2GetLinks,
attach: _transactionV2Attach,
version: '3.0.5',
version: '3.1.8',
);
int _transactionV2EstimateSize(

View file

@ -7,7 +7,7 @@ part of 'contact_entry.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetContactEntryCollection on Isar {
IsarCollection<ContactEntry> get contactEntrys => this.collection();
@ -69,7 +69,7 @@ const ContactEntrySchema = CollectionSchema(
getId: _contactEntryGetId,
getLinks: _contactEntryGetLinks,
attach: _contactEntryAttach,
version: '3.0.5',
version: '3.1.8',
);
int _contactEntryEstimateSize(
@ -1142,7 +1142,7 @@ extension ContactEntryQueryProperty
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const ContactAddressEntrySchema = Schema(
name: r'ContactAddressEntry',

View file

@ -7,7 +7,7 @@ part of 'encrypted_string_value.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetEncryptedStringValueCollection on Isar {
IsarCollection<EncryptedStringValue> get encryptedStringValues =>
@ -54,7 +54,7 @@ const EncryptedStringValueSchema = CollectionSchema(
getId: _encryptedStringValueGetId,
getLinks: _encryptedStringValueGetLinks,
attach: _encryptedStringValueAttach,
version: '3.0.5',
version: '3.1.8',
);
int _encryptedStringValueEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'eth_contract.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetEthContractCollection on Isar {
IsarCollection<EthContract> get ethContracts => this.collection();
@ -74,7 +74,7 @@ const EthContractSchema = CollectionSchema(
getId: _ethContractGetId,
getLinks: _ethContractGetLinks,
attach: _ethContractAttach,
version: '3.0.5',
version: '3.1.8',
);
int _ethContractEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'lelantus_coin.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetLelantusCoinCollection on Isar {
IsarCollection<LelantusCoin> get lelantusCoins => this.collection();
@ -101,7 +101,7 @@ const LelantusCoinSchema = CollectionSchema(
getId: _lelantusCoinGetId,
getLinks: _lelantusCoinGetLinks,
attach: _lelantusCoinAttach,
version: '3.0.5',
version: '3.1.8',
);
int _lelantusCoinEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'log.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetLogCollection on Isar {
IsarCollection<Log> get logs => this.collection();
@ -59,7 +59,7 @@ const LogSchema = CollectionSchema(
getId: _logGetId,
getLinks: _logGetLinks,
attach: _logAttach,
version: '3.0.5',
version: '3.1.8',
);
int _logEstimateSize(

View file

@ -0,0 +1,35 @@
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import 'package:isar/isar.dart';
part 'sent_to_address.g.dart';
@Collection()
class SentToAddress {
SentToAddress({
required this.walletId,
required this.txid,
required this.value,
this.label = "",
});
Id id = Isar.autoIncrement;
@Index()
late final String walletId;
@Index(unique: true, composite: [CompositeIndex("walletId")])
late final String txid;
late final String value;
late final String label;
}

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ part of 'transaction_note.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetTransactionNoteCollection on Isar {
IsarCollection<TransactionNote> get transactionNotes => this.collection();
@ -76,7 +76,7 @@ const TransactionNoteSchema = CollectionSchema(
getId: _transactionNoteGetId,
getLinks: _transactionNoteGetLinks,
attach: _transactionNoteAttach,
version: '3.0.5',
version: '3.1.8',
);
int _transactionNoteEstimateSize(

View file

@ -7,7 +7,7 @@ part of 'ordinal.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetOrdinalCollection on Isar {
IsarCollection<Ordinal> get ordinals => this.collection();
@ -83,7 +83,7 @@ const OrdinalSchema = CollectionSchema(
getId: _ordinalGetId,
getLinks: _ordinalGetLinks,
attach: _ordinalAttach,
version: '3.0.5',
version: '3.1.8',
);
int _ordinalEstimateSize(

View file

@ -13,6 +13,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import '../../app_config.dart';
import '../../utilities/extensions/impl/box_shadow.dart';
import '../../utilities/extensions/impl/gradient.dart';
@ -1884,10 +1885,7 @@ class StackTheme {
(map[mainNetId] as String).toBigIntFromHex.toInt(),
);
} else {
Logging.instance.log(
"Color not found in theme for $mainNetId",
level: LogLevel.Error,
);
Logging.instance.w("Color not found in theme for $mainNetId");
}
}

View file

@ -7,7 +7,7 @@ part of 'stack_theme.dart';
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetStackThemeCollection on Isar {
IsarCollection<StackTheme> get stackThemes => this.collection();
@ -860,7 +860,7 @@ const StackThemeSchema = CollectionSchema(
getId: _stackThemeGetId,
getLinks: _stackThemeGetLinks,
attach: _stackThemeAttach,
version: '3.0.5',
version: '3.1.8',
);
int _stackThemeEstimateSize(
@ -18012,7 +18012,7 @@ extension StackThemeQueryProperty
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const ThemeAssetsSchema = Schema(
name: r'ThemeAssets',
@ -25833,7 +25833,7 @@ extension ThemeAssetsQueryObject
on QueryBuilder<ThemeAssets, ThemeAssets, QFilterCondition> {}
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const ThemeAssetsV2Schema = Schema(
name: r'ThemeAssetsV2',
@ -29441,7 +29441,7 @@ extension ThemeAssetsV2QueryObject
on QueryBuilder<ThemeAssetsV2, ThemeAssetsV2, QFilterCondition> {}
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
const ThemeAssetsV3Schema = Schema(
name: r'ThemeAssetsV3',

View file

@ -0,0 +1,164 @@
import 'dart:convert';
import '../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart';
import 'key_data_interface.dart';
// do not remove or change the order of these enum values
enum ViewOnlyWalletType {
cryptonote,
addressOnly,
xPub;
}
sealed class ViewOnlyWalletData with KeyDataInterface {
@override
final String walletId;
ViewOnlyWalletType get type;
ViewOnlyWalletData({
required this.walletId,
});
static ViewOnlyWalletData fromJsonEncodedString(
String jsonEncodedString, {
required String walletId,
}) {
final map = jsonDecode(jsonEncodedString) as Map;
final json = Map<String, dynamic>.from(map);
final type = ViewOnlyWalletType.values[json["type"] as int];
switch (type) {
case ViewOnlyWalletType.cryptonote:
return CryptonoteViewOnlyWalletData.fromJsonEncodedString(
jsonEncodedString,
walletId: walletId,
);
case ViewOnlyWalletType.addressOnly:
return AddressViewOnlyWalletData.fromJsonEncodedString(
jsonEncodedString,
walletId: walletId,
);
case ViewOnlyWalletType.xPub:
return ExtendedKeysViewOnlyWalletData.fromJsonEncodedString(
jsonEncodedString,
walletId: walletId,
);
}
}
String toJsonEncodedString();
}
class CryptonoteViewOnlyWalletData extends ViewOnlyWalletData {
@override
final type = ViewOnlyWalletType.cryptonote;
final String address;
final String privateViewKey;
CryptonoteViewOnlyWalletData({
required super.walletId,
required this.address,
required this.privateViewKey,
});
static CryptonoteViewOnlyWalletData fromJsonEncodedString(
String jsonEncodedString, {
required String walletId,
}) {
final map = jsonDecode(jsonEncodedString) as Map;
final json = Map<String, dynamic>.from(map);
return CryptonoteViewOnlyWalletData(
walletId: walletId,
address: json["address"] as String,
privateViewKey: json["privateViewKey"] as String,
);
}
@override
String toJsonEncodedString() => jsonEncode({
"type": type.index,
"address": address,
"privateViewKey": privateViewKey,
});
}
class AddressViewOnlyWalletData extends ViewOnlyWalletData {
@override
final type = ViewOnlyWalletType.addressOnly;
final String address;
AddressViewOnlyWalletData({
required super.walletId,
required this.address,
});
static AddressViewOnlyWalletData fromJsonEncodedString(
String jsonEncodedString, {
required String walletId,
}) {
final map = jsonDecode(jsonEncodedString) as Map;
final json = Map<String, dynamic>.from(map);
return AddressViewOnlyWalletData(
walletId: walletId,
address: json["address"] as String,
);
}
@override
String toJsonEncodedString() => jsonEncode({
"type": type.index,
"address": address,
});
}
class ExtendedKeysViewOnlyWalletData extends ViewOnlyWalletData {
@override
final type = ViewOnlyWalletType.xPub;
final List<XPub> xPubs;
ExtendedKeysViewOnlyWalletData({
required super.walletId,
required List<XPub> xPubs,
}) : xPubs = List.unmodifiable(xPubs);
static ExtendedKeysViewOnlyWalletData fromJsonEncodedString(
String jsonEncodedString, {
required String walletId,
}) {
final map = jsonDecode(jsonEncodedString) as Map;
final json = Map<String, dynamic>.from(map);
return ExtendedKeysViewOnlyWalletData(
walletId: walletId,
xPubs: List<Map<String, dynamic>>.from((json["xPubs"] as List))
.map(
(e) => XPub(
path: e["path"] as String,
encoded: e["encoded"] as String,
),
)
.toList(growable: false),
);
}
@override
String toJsonEncodedString() => jsonEncode({
"type": type.index,
"xPubs": [
...xPubs.map(
(e) => {
"path": e.path,
"encoded": e.encoded,
},
),
],
});
}

View file

@ -0,0 +1,25 @@
enum DNSAddressType {
IPv4,
IPv6,
Tor,
Freenet,
I2P,
ZeroNet;
String get key {
switch (this) {
case DNSAddressType.IPv4:
return "ip";
case DNSAddressType.IPv6:
return "ip6";
case DNSAddressType.Tor:
return "_tor";
case DNSAddressType.Freenet:
return "freenet";
case DNSAddressType.I2P:
return "i2p";
case DNSAddressType.ZeroNet:
return "zeronet";
}
}
}

View file

@ -0,0 +1,129 @@
import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:namecoin/namecoin.dart';
import '../../utilities/extensions/extensions.dart';
import 'dns_record_type.dart';
@Immutable()
abstract class DNSRecordBase {
final String name;
DNSRecordBase({required this.name});
String getValueString();
}
@Immutable()
final class RawDNSRecord extends DNSRecordBase {
final String value;
RawDNSRecord({required super.name, required this.value});
@override
String getValueString() => value;
@override
String toString() {
return "RawDNSRecord(name: $name, value: $value)";
}
}
@Immutable()
final class DNSRecord extends DNSRecordBase {
final DNSRecordType type;
final Map<String, dynamic> data;
DNSRecord({
required super.name,
required this.type,
required this.data,
});
@override
String getValueString() {
// TODO error handling
dynamic value = data;
while (value is Map) {
value = value[value.keys.first];
}
return value.toString();
}
DNSRecord copyWith({
DNSRecordType? type,
Map<String, dynamic>? data,
}) {
return DNSRecord(
type: type ?? this.type,
data: data ?? this.data,
name: name,
);
}
@override
String toString() {
return "DNSRecord(name: $name, type: $type, data: $data)";
}
static String merge(List<DNSRecord> records) {
final Map<String, dynamic> result = {};
for (final record in records) {
switch (record.type) {
case DNSRecordType.CNAME:
if (result[record.data.keys.first] != null) {
throw Exception("CNAME record already exists");
}
_deepMerge(result, record.data);
break;
case DNSRecordType.TLS:
case DNSRecordType.NS:
case DNSRecordType.DS:
case DNSRecordType.SRV:
case DNSRecordType.SSH:
case DNSRecordType.TXT:
case DNSRecordType.IMPORT:
case DNSRecordType.A:
_deepMerge(result, record.data);
break;
}
}
final string = jsonEncode(result);
if (string.toUint8ListFromUtf8.length > valueMaxLength) {
throw Exception(
"Value length (${string.toUint8ListFromUtf8.length}) exceeds maximum"
" allowed ($valueMaxLength)",
);
}
return string;
}
}
void _deepMerge(Map<String, dynamic> base, Map<String, dynamic> updates) {
updates.forEach((key, value) {
if (value is Map<String, dynamic> && base[key] is Map<String, dynamic>) {
_deepMerge(base[key] as Map<String, dynamic>, value);
} else if (value is List && base[key] is List) {
(base[key] as List).addAll(value);
} else {
if (base[key] != null) {
throw Exception(
"Attempted to overwrite value: ${base[key]} where key=$key",
);
}
if (value is Map) {
base[key] = Map<String, dynamic>.from(value);
} else if (value is List) {
base[key] = List<dynamic>.from(value);
} else {
base[key] = value;
}
}
});
}

View file

@ -0,0 +1,68 @@
enum DNSRecordType {
A,
CNAME,
NS,
DS,
TLS,
SRV,
TXT,
IMPORT,
SSH;
String get info {
switch (this) {
case DNSRecordType.A:
return "An A record maps your domain to an address (IPv4, IPv6, Tor,"
" Freenet, I2P, or ZeroNet).";
case DNSRecordType.CNAME:
return "A CNAME record redirects your domain to another domain,"
" essentially acting as an alias.";
case DNSRecordType.NS:
return "An NS record specifies the nameservers that are authoritative"
" for your domain.";
case DNSRecordType.DS:
return "A DS record holds information about DNSSEC (DNS Security "
"Extensions) for your domain, helping with verification and "
"integrity.";
case DNSRecordType.TLS:
return "A TLS record is used for specifying details about how to "
"establish secure connections (like TLS certificates) for your"
" domain.";
case DNSRecordType.SRV:
return "An SRV record specifies the location of servers for specific"
" services, such as SIP, XMPP, or Minecraft servers.";
case DNSRecordType.TXT:
return "A TXT record allows you to add arbitrary text to your domain's"
" DNS record, often used for verification (e.g., SPF, DKIM).";
case DNSRecordType.IMPORT:
return "An IMPORT record is used to bring in DNS records from an"
" external source into your domain's configuration.";
case DNSRecordType.SSH:
return "An SSH record provides information related to SSH public keys"
" for securely connecting to your domain's services.";
}
}
String? get key {
switch (this) {
case DNSRecordType.A:
return null;
case DNSRecordType.CNAME:
return "alias";
case DNSRecordType.NS:
return "ns";
case DNSRecordType.DS:
return "ds";
case DNSRecordType.TLS:
return "tls";
case DNSRecordType.SRV:
return "srv";
case DNSRecordType.TXT:
return "txt";
case DNSRecordType.IMPORT:
return "import";
case DNSRecordType.SSH:
return "sshfp";
}
}
}

View file

@ -9,6 +9,7 @@
*/
import 'package:hive/hive.dart';
import '../utilities/default_nodes.dart';
import '../utilities/flutter_secure_storage_interface.dart';
@ -38,6 +39,10 @@ class NodeModel {
final bool isDown;
// @HiveField(10)
final bool? trusted;
// @HiveField(11)
final bool torEnabled;
// @HiveField(12)
final bool clearnetEnabled;
NodeModel({
required this.host,
@ -49,6 +54,8 @@ class NodeModel {
required this.coinName,
required this.isFailover,
required this.isDown,
required this.torEnabled,
required this.clearnetEnabled,
this.loginName,
this.trusted,
});
@ -58,12 +65,14 @@ class NodeModel {
int? port,
String? name,
bool? useSSL,
String? loginName,
required String? loginName,
bool? enabled,
String? coinName,
bool? isFailover,
bool? isDown,
bool? trusted,
required bool? trusted,
bool? torEnabled,
bool? clearnetEnabled,
}) {
return NodeModel(
host: host ?? this.host,
@ -71,12 +80,14 @@ class NodeModel {
name: name ?? this.name,
id: id,
useSSL: useSSL ?? this.useSSL,
loginName: loginName ?? this.loginName,
loginName: loginName,
enabled: enabled ?? this.enabled,
coinName: coinName ?? this.coinName,
isFailover: isFailover ?? this.isFailover,
isDown: isDown ?? this.isDown,
trusted: trusted ?? this.trusted,
trusted: trusted,
torEnabled: torEnabled ?? this.torEnabled,
clearnetEnabled: clearnetEnabled ?? this.clearnetEnabled,
);
}
@ -98,6 +109,8 @@ class NodeModel {
map['isFailover'] = isFailover;
map['isDown'] = isDown;
map['trusted'] = trusted;
map['torEnabled'] = torEnabled;
map['clearEnabled'] = clearnetEnabled;
return map;
}

View file

@ -28,13 +28,15 @@ class NodeModelAdapter extends TypeAdapter<NodeModel> {
isFailover: fields[8] as bool,
isDown: fields[9] as bool,
trusted: fields[10] as bool?,
torEnabled: fields[11] as bool? ?? true,
clearnetEnabled: fields[12] as bool? ?? true,
);
}
@override
void write(BinaryWriter writer, NodeModel obj) {
writer
..writeByte(11)
..writeByte(13)
..writeByte(0)
..write(obj.id)
..writeByte(1)
@ -56,7 +58,11 @@ class NodeModelAdapter extends TypeAdapter<NodeModel> {
..writeByte(9)
..write(obj.isDown)
..writeByte(10)
..write(obj.trusted);
..write(obj.trusted)
..writeByte(11)
..write(obj.torEnabled)
..writeByte(12)
..write(obj.clearnetEnabled);
}
@override

View file

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:socks5_proxy/socks_client.dart';
import '../utilities/logger.dart';
// WIP wrapper layer
@ -52,10 +53,7 @@ class HTTP {
response.statusCode,
);
} catch (e, s) {
Logging.instance.log(
"HTTP.get() rethrew: $e\n$s",
level: LogLevel.Info,
);
Logging.instance.w("HTTP.get() rethrew: ", error: e, stackTrace: s);
rethrow;
} finally {
httpClient.close(force: true);
@ -98,10 +96,7 @@ class HTTP {
response.statusCode,
);
} catch (e, s) {
Logging.instance.log(
"HTTP.post() rethrew: $e\n$s",
level: LogLevel.Info,
);
Logging.instance.w("HTTP.post() rethrew: ", error: e, stackTrace: s);
rethrow;
} finally {
httpClient.close(force: true);
@ -118,6 +113,11 @@ class HTTP {
onDone: () => completer.complete(
Uint8List.fromList(bytes),
),
onError: (Object err, StackTrace s) => Logging.instance.e(
"Http wrapper layer listen",
error: err,
stackTrace: s,
),
);
return completer.future;
}

View file

@ -10,7 +10,6 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -69,6 +68,7 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
...AppConfig.coins.where((e) => e.network == CryptoCurrencyNetwork.main),
];
final List<AddWalletListEntity> coinEntities = [];
final List<AddWalletListEntity> coinTestnetEntities = [];
final List<EthTokenEntity> tokenEntities = [];
final bool isDesktop = Util.isDesktop;
@ -130,16 +130,11 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
void initState() {
_searchFieldController = TextEditingController();
_searchFocusNode = FocusNode();
// _coinsTestnet.remove(Coin.firoTestNet);
if (Util.isDesktop && !kDebugMode) {
_coins.removeWhere((e) => e is BitcoinFrost);
}
coinEntities.addAll(_coins.map((e) => CoinEntity(e)));
if (ref.read(prefsChangeNotifierProvider).showTestNetCoins) {
coinEntities.addAll(_coinsTestnet.map((e) => CoinEntity(e)));
coinTestnetEntities.addAll(_coinsTestnet.map((e) => CoinEntity(e)));
}
if (AppConfig.coins.whereType<Ethereum>().isNotEmpty) {
@ -158,7 +153,12 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
}
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.refresh(addWalletSelectedEntityStateProvider);
if (mounted) {
ref.refresh(addWalletSelectedEntityStateProvider);
if (isDesktop) {
_searchFocusNode.requestFocus();
}
}
});
super.initState();
@ -286,6 +286,14 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
initialState: ExpandableState.expanded,
animationDurationMultiplier: 0.5,
),
if (coinTestnetEntities.isNotEmpty)
ExpandingSubListItem(
title: "Testnet",
entities:
filter(_searchTerm, coinTestnetEntities),
initialState: ExpandableState.expanded,
animationDurationMultiplier: 0.5,
),
if (tokenEntities.isNotEmpty)
ExpandingSubListItem(
title: "Tokens",
@ -419,6 +427,13 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
entities: filter(_searchTerm, coinEntities),
initialState: ExpandableState.expanded,
),
if (coinTestnetEntities.isNotEmpty)
ExpandingSubListItem(
title: "Testnet",
entities:
filter(_searchTerm, coinTestnetEntities),
initialState: ExpandableState.expanded,
),
if (tokenEntities.isNotEmpty)
ExpandingSubListItem(
title: "Tokens",

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../../frost_route_generator.dart';
import '../../../../wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../../services/frost.dart';
import '../../../../../utilities/logger.dart';
@ -15,6 +15,7 @@ import '../../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../../widgets/frost_step_user_steps.dart';
import '../../../../../widgets/stack_dialog.dart';
import '../../../../../widgets/textfields/frost_step_field.dart';
import '../../../../wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart';
class FrostCreateStep2 extends ConsumerStatefulWidget {
const FrostCreateStep2({
@ -177,10 +178,7 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
.routeName,
);
} catch (e, s) {
Logging.instance.log(
"$e\n$s",
level: LogLevel.Fatal,
);
Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
if (context.mounted) {
return await showDialog<void>(
context: context,

View file

@ -178,10 +178,7 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
.routeName,
);
} catch (e, s) {
Logging.instance.log(
"$e\n$s",
level: LogLevel.Fatal,
);
Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
if (context.mounted) {
return await showDialog<void>(

View file

@ -219,10 +219,7 @@ class _FrostCreateStep5State extends ConsumerState<FrostCreateStep5> {
);
}
} catch (e, s) {
Logging.instance.log(
"$e\n$s",
level: LogLevel.Fatal,
);
Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
// pop progress dialog
if (context.mounted && !progressPopped) {

View file

@ -81,10 +81,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
);
}
} catch (e, s) {
Logging.instance.log(
"$e\n$s",
level: LogLevel.Fatal,
);
Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
if (mounted) {
await showDialog<void>(

Some files were not shown because too many files have changed in this diff Show more