From 55005f8b39b2b904507253227d1ff1cb7da5d86d Mon Sep 17 00:00:00 2001 From: OmarHatem <omarh.ismail1@gmail.com> Date: Wed, 8 Jan 2025 05:09:45 +0200 Subject: [PATCH 1/9] await settings migration --- lib/entities/default_settings_migration.dart | 30 +++++++++++++------- scripts/android/app_env.sh | 2 +- scripts/ios/app_env.sh | 2 +- scripts/linux/app_env.sh | 2 +- scripts/macos/app_env.sh | 2 +- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 25140f106..90e32d982 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -70,8 +70,13 @@ Future<void> defaultSettingsMigration( await sharedPreferences.setBool(PreferencesKey.isNewInstall, isNewInstall); - final currentVersion = + int currentVersion = sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) ?? 0; + // TODO: remove after v4.22.1 is live + /// for beta testers who didn't correctly get the 46 step configured + if (currentVersion == 46) { + currentVersion--; + } if (currentVersion >= version) { return; @@ -334,20 +339,20 @@ Future<void> defaultSettingsMigration( ); break; case 46: - _fixNodesUseSSLFlag(nodes); - updateWalletTypeNodesWithNewNode( + await _fixNodesUseSSLFlag(nodes); + await updateWalletTypeNodesWithNewNode( newNodeUri: 'litecoin.stackwallet.com:20063', nodes: nodes, type: WalletType.litecoin, useSSL: true, ); - updateWalletTypeNodesWithNewNode( + await updateWalletTypeNodesWithNewNode( newNodeUri: 'electrum-ltc.bysh.me:50002', nodes: nodes, type: WalletType.litecoin, useSSL: true, ); - _changeDefaultNode( + await _changeDefaultNode( nodes: nodes, sharedPreferences: sharedPreferences, type: WalletType.solana, @@ -360,13 +365,13 @@ Future<void> defaultSettingsMigration( 'solana-rpc.publicnode.com:443', ], ); - _updateNode( + await _updateNode( nodes: nodes, currentUri: "ethereum.publicnode.com", newUri: "ethereum-rpc.publicnode.com", useSSL: true, ); - _updateNode( + await _updateNode( nodes: nodes, currentUri: "polygon-bor.publicnode.com", newUri: "polygon-bor-rpc.publicnode.com", @@ -387,13 +392,16 @@ Future<void> defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } -void _updateNode({ +Future<void> _updateNode({ required Box<Node> nodes, required String currentUri, String? newUri, bool? useSSL, -}) { +}) async { for (Node node in nodes.values) { + print("@@@@@@@@@@@@@"); + print(node.uriRaw); + print(node.uri); if (node.uriRaw == currentUri) { if (newUri != null) { node.uriRaw = newUri; @@ -401,6 +409,7 @@ void _updateNode({ if (useSSL != null) { node.useSSL = useSSL; } + await node.save(); } } } @@ -481,7 +490,7 @@ void _deselectExchangeProvider(SharedPreferences sharedPreferences, String provi ); } -void _fixNodesUseSSLFlag(Box<Node> nodes) { +Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async { for (Node node in nodes.values) { switch (node.uriRaw) { case cakeWalletLitecoinElectrumUri: @@ -490,6 +499,7 @@ void _fixNodesUseSSLFlag(Box<Node> nodes) { case newCakeWalletMoneroUri: node.useSSL = true; node.trusted = true; + await node.save(); } } } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 6b1907451..45e28379d 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -23,7 +23,7 @@ MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.22.1" -CAKEWALLET_BUILD_NUMBER=241 +CAKEWALLET_BUILD_NUMBER=242 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index c1747c502..079b12391 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -19,7 +19,7 @@ MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.22.1" -CAKEWALLET_BUILD_NUMBER=288 +CAKEWALLET_BUILD_NUMBER=289 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/linux/app_env.sh b/scripts/linux/app_env.sh index f0ec8e9e6..5103eeccc 100755 --- a/scripts/linux/app_env.sh +++ b/scripts/linux/app_env.sh @@ -15,7 +15,7 @@ fi CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="1.12.1" -CAKEWALLET_BUILD_NUMBER=42 +CAKEWALLET_BUILD_NUMBER=43 if ! [[ " ${TYPES[*]} " =~ " ${APP_LINUX_TYPE} " ]]; then echo "Wrong app type." diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index fe3d806d8..af2b6ab1e 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -22,7 +22,7 @@ MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="1.15.1" -CAKEWALLET_BUILD_NUMBER=100 +CAKEWALLET_BUILD_NUMBER=101 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From eb2827402a1bccf1b938306099770b17e6483496 Mon Sep 17 00:00:00 2001 From: OmarHatem <omarh.ismail1@gmail.com> Date: Wed, 8 Jan 2025 05:12:57 +0200 Subject: [PATCH 2/9] revert beta testers change --- lib/entities/default_settings_migration.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 90e32d982..abcdda4c0 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -70,13 +70,8 @@ Future<void> defaultSettingsMigration( await sharedPreferences.setBool(PreferencesKey.isNewInstall, isNewInstall); - int currentVersion = + final currentVersion = sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) ?? 0; - // TODO: remove after v4.22.1 is live - /// for beta testers who didn't correctly get the 46 step configured - if (currentVersion == 46) { - currentVersion--; - } if (currentVersion >= version) { return; From b865e5e38bc5c154588147a4057f216899168c03 Mon Sep 17 00:00:00 2001 From: Kainoa Kanter <kainoakanter@gmail.com> Date: Sat, 11 Jan 2025 06:05:25 -0800 Subject: [PATCH 3/9] Closes #873 (#1928) --- .../mipmap-anydpi-v26/ic_launcher.xml | 1 + .../mipmap-hdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 2359 bytes .../mipmap-mdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 1544 bytes .../mipmap-xhdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 3285 bytes .../mipmap-xxhdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 5258 bytes .../mipmap-xxxhdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 7640 bytes .../mipmap-anydpi-v26/ic_launcher.xml | 1 + .../mipmap-hdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 2316 bytes .../mipmap-mdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 1518 bytes .../mipmap-xhdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 3110 bytes .../mipmap-xxhdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 4880 bytes .../mipmap-xxxhdpi/ic_launcher_adaptive_mono.png | Bin 0 -> 6978 bytes 12 files changed, 2 insertions(+) create mode 100644 assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png create mode 100644 assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png diff --git a/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml b/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml index 00d924171..c8bd4b26c 100644 --- a/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml +++ b/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml @@ -2,4 +2,5 @@ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@mipmap/ic_launcher_adaptive_back"/> <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/> + <monochrome android:drawable="@mipmap/ic_launcher_adaptive_mono"/> </adaptive-icon> \ No newline at end of file diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..27f939b416b899a04ebf6312ab9e99a322e3af8a GIT binary patch literal 2359 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 N2OAgbiZkB#{s!nGQz8HW literal 0 HcmV?d00001 diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..7bdb298c127e13a9b405704250496ca40f8c2eeb GIT binary patch literal 1544 zcmZ{kdpHw%7{`Az5$5vL!`yReJ5HK5*R0%TVhqDLxyHr_i?Kw~Rx0<1X<DvPO09@V zR4$Pdb33R=is+);N^)>GJI{HZbDqxgoIl?8`@HY_eBSRr@AIaST<m3~Riyy{vIGab zyGSGdiml?JjEE{ZAQCOAgS#^T$B_WA&j7G0YOy~6a1;%|OdtT*0s!FAg^h0eMFTO4 zlRX}6req77MU^Cz;A|)P5dwuuLOwX2d;oy>X9C`a96vhCiz0e@f)<v1fHp}g=&Xue z)&)9(ylXn0aQ_=*WL0;s?-4qmKPr^JzdE!Uc+>P=G$-kU2j6cw1?7ad>_0aW<79?u zwLZI~%~QOVz1iQC)bL(&F8SDelHZ;p{e8_}Ct~`{zt67k{a(CTIuK^8nsuQ3U*Y}k z9DJT-l}ypBII~Z0Czpt9AX+_SG74m>rvJFmgSAAQn@~W0e3P{6DapTogyaZ?YvkwJ z%17ngX>9pOYI8yU#<|;u7^juZoNlUN^D~9+UDEI4<9eIpOE|H@N{-^AtJZ>cVsYq- zv;YQksr3`27H#z<h?j;0q8+lri+<+MLI{^85{Ge0^Ac48ZsafyxkqAo8_&nQ>MYUA zkmq%3d%L-vS##67C^;v(f2Wk|RZGi?b1$ciF72K+f23up8|rbeu5{eCst9|V5pP<8 zDwL<vTMeI=4Tc0DXBK5-4l5iA3**7q76v{VoURkz<k})rmu=-4UgPEI#7m7ASufy7 zzM=tt!Zqf>NsFk(&~)|6g!~A*Vt1wM7i($<-9G6h==7=fHVn;RG)X8-o>(U>k-g8Z zxQBS$*g*G|2g<PM7j>B?x2YE#uTG2ByeiM!k@uv2D5a_yJNuMYm`Ls>Ug#;c#XJW& zwyr!Mn#XqD(QJE-%g|W4b*uz~(yr_fF2!>48B@_Zkf{xuA<KA2#wa9iXX_;?*MWr` zq8f6CUa;Sj-B2ASC7LA2>5!AG$p_>#+5}Q7*$U4y=?>5T28YZ&ZqaJ>w}B75ep%G0 zOjU=x!GJ6KWp}Q)RG6lJGMj8vgI?dF)izVwvCh~TlB5B@@r-m+k*zvFeWm9P&)_aH zw2}=j+_Mqn5@wz{UUsn9y>=a^m0|<qK^hd<rZ9utEn|C1=u4h*@b!o3H|%HMPVx}3 z!(xx?#128+;=lr;zfHM1z)~&OraCc8gM(Rv#GhhFvv+Odh&dGmLvw;Y&Bkr<$FodK zIflzLhJ`NG%T3&PpzC#ugw8F=-n%7Af%nxtaZ&x0jW8E)YB@#c3lDX~2uxcm!O<)E zsSPRg`V-nJFxJ#)HmX*Z#k$x>&M1gs?5N4YJqf<7qP!8%@m6lp6-1MlLV@C#!Ny%x z>4=rOuKJe2c5Bhr1y%iLBa`(YryIdwxldj4vDn~Bi*7HVd~K`MuLZVXKegKff;ZQn zw{qiCD?4n2yllm<+*AVEVa#;NL>X~pt+OykMyjkOQR0tODu48G!o?~t0?kb|LQ_7r z*Y;*clV^soou1z{>KZ^Sf7{i$b4P4)cpABZudi91WS0M#7U{F9P}02t>v}=+wU$lQ zAL$*p6;OSCavea;f4NbSsdHDkj2m|{m~@RlZS-Y@mzB8%^`2{(Em-5yYT}}*xqibq zkD)|kx!ED?T>X^uOFAY@#`ST@_{Iy#p=!J(buN3>vBrwFAd^AX_ZA+pukEJV50)nD z3_B{d&e^CHUcn1;JNBJQS6Pa^6OPC$?Mui^2`#4-7Yi{`GrNbShjomkCYOA}cx%D$ zJ|@`ZB_y;BQR+iaLl2enoP-`@N#}8SOn0kel?|JBV!wBc;SAiKqz$^tzfy1X>3bFN zpAVzj<N1Wub5BWZxqttp=oKQEb_bckLCg>=H6}zPzz}U{f<j|ZXd^P(5Nl+N#hB`& z(O5M4ox)q#4*)$X_%JQu{{gPEZ?y=}`^SNKm>v?#45CN>z!+iCW>_@lZxfo5^@@lA N1Unb}ZCv2#KLH{Bp9lZ| literal 0 HcmV?d00001 diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..79e9df08d83daea66bec94b669062a82b6603e4f GIT binary patch literal 3285 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 B0Pp|+ literal 0 HcmV?d00001 diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb1c74308757dc2319eb2a63bbcc81cab2fd95c GIT binary patch literal 5258 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 K2WU;ZsQ&`>vhJP$ literal 0 HcmV?d00001 diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..205f2ad2a5ab1a7a704a5b3bbab36249aeb2be4f GIT binary patch literal 7640 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 Kx#E>o_<sRfUWo?) literal 0 HcmV?d00001 diff --git a/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml b/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml index 00d924171..c8bd4b26c 100644 --- a/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml +++ b/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml @@ -2,4 +2,5 @@ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@mipmap/ic_launcher_adaptive_back"/> <foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/> + <monochrome android:drawable="@mipmap/ic_launcher_adaptive_mono"/> </adaptive-icon> \ No newline at end of file diff --git a/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..af8126ea9fd3293c46c1c46dd153d14a251b55e9 GIT binary patch literal 2316 zcma);X)qg#7RTdKv4x^kR45utQ3<6I(V~h7QN&If)ZP$8QMs-*Z7o%lSZax?TH5<8 zC8ebrx3RCSwCG~1t+Aw*)^bH%cizmKxgXxVH*?PU&-tJE&G~pv%0;XdNJL%)004l{ z))tNj`ta`*5;&+qyAzoQa@^0_(GCE(rUn2c-UI;tJg^eK0szr40AP^-03h=LfTN_M zW(U;4;1^$vl?7lwDWjix&;iM4y9+=LA3r}3!o#R+95}0J3o~5o$CV-?N#;Gc>$fd) zsZt9ebh)JY5#{8p#`EQkeur@QREU&ZXR1+1;K}s&mR3a^+v2OpQY9PD%En?2!^uB! zIAQS)GQkv9n(y+?ET03ckT-u`TBUj7rfGK{v}f~tm|^_ZL`(c;K+KT;E^iPh9$&IR zqMut>rkm)B-Z(Dwze5y0F4OH;<{0AEZ-;X*1G7`~`=QMU`x}NHXp(abbjA795no)S zgx2%Ij&_JnEr}*OF)u`I*7COQ_czw@>R6>Uf3SkE$*%ZwPHuh2#Nuc}1;`IQ1I?^A zT{y+r?Gv+w*3{+ctK-vO36L&|Bnbst(~F7*%Ba16*;!R9m0sS58p4hLam%czivu!k zTl;>ti6agVI=Stc_)B{ESvnbf!kevKrb80$8pfY3Gae&UNidFmVxN0q7Sr~#;qK*R zDS0_Yy=lywpX*0dl`%oE_R;916?OZdOj4#@Gix*3jy{>HULsgE3TZ5%+{dU)&*rm& zK~lFr-=qGDPHnhTxc(jTs5qO<?h=A}*+UKbo$~h;d_`-4^3L6;Vpj~ZQ^Fk`e4F5u z-*slkWI=(FRK<ocnA(qq$|y&7pcpStPvK~Ve&ls{x8=CmE+&mi7g!EdpHuAJ7a1^A z20k1S@yV|2siA7G^K{!km<K8|UO$k1Vq;W;g67Qb@>1`mE$O>k$TVpBCW<oHgQmCb zpe^n|vGv2Xx1b(wsG84$Ep9o}tu&>LQ?6HXO%w?6oy*aZx|T#QBTKlFrp*|dSP+=@ zg8^GM65)wnV(e&-KuCwLxX@Nn7&b3A(wc)s_R}@6WcQS}54Qs%VhUXO_Y@T`l+<Bk z9+=gSJvGKY`sP8giS3xlAD%inB>P5Oyd)TxH3jNJTElCv<-Tbn(3CDXbsFtE3hhh1 zudve2a517=Zl`k-sZ%cHRxAl^MNk|jh>&U9(qJi&gHFQQ*zJ1QXJlW|^wHE&;W;ZW zLn@-vn3XkqDNc$Vp<jw|+=XW9W}eZ0G$<i|r($m}U||ydtkRjIRuOeP=UdZfAJsO> zt<^%E&3#zyPk}0zu)E=Kep^Wp{vDVx`AG+-2EiLdJ);<`<cV{qY39NMS03rE^!oJ+ zSss_+$*#E^Dr5z4%__zcj9DSBV2P*qv>HQY{v~Fi1m(#_l>Xj<@EG6~XfxHH4>@$I zEfT9qY2gCO8S)8tzP=h*7wEx-<r4q&DH7+F=_JJjSSc=q{vq_}#-z$%#53#s7xEPg zbsPd{#l0qQse1;u^a(iMl+10~!s@%u5pufMlY=WxS!oGq_*d+&S4}r1chtyA>(LM& zi=Rd>1}sK4nkTxEEy%h<u&4`$lAUhtd5(zC%CG?Gy~n(Hg?(q}^^*pVAGE?3L*VeL zo&?1ZS>SWk9D9;3(NzD37uNezFTP=f!zSzny$+Wgmq_&vpFcHQrxD21^aF;*-MZGG zdaj+WutK6unC3*bg-hzTc;E_Nu!BcIeI+u>XN-RYH{O>D^T}9IgPDbsEqL$V`}!Is z^eQilOz3&e7<qnJSe*)aALBI~E;-cfp$*SCji2TRw&+dRW=Dv|JH?NwDcaqh+hXxO znY}UTxrA-@=${pRnb-TRVu<!-5}Z4?9Qdov*Xrd#$I%$DZQL;);`G2Tf#t7HkBFv2 zwe1^Ld=aapk3G~Aqa1O4x3G(c*YamX#v==VAmoWwajLq$w!!fc)#ru#yjw-F7R+xc zf;u9{(n{vh`j`AZxkugked~xKp_}I^7F3~SdiV5dzBy)j#*+PNxV{U<{Ei=dI%9yz z8Gf8I>4D<9e!iMz5<U0SgfW%kE?ZK>4IP0`ZNy=W+C0YjfUGE+X{9EL)rrpZm*O>` z)kH3V`Y?+RDvYn+ZVy_e#8zuPsV0d%WB*X4XbptQ1foo^DzUnZdh@ke)8WR^Yii7k zAsq{`hASy3gVYka)F_Lcnt*djG5Wf1=ce8ciuPkSG`?h<=6EUyrGt7a-Lg<QYw~V3 z5ax_Po{l#&sf?GF1J3qoh?C~0s?yV?yrtU*#_`->S}Q`fIslgE!JRTZn^(q~=s@>v zB+$8ad-GU(YObMS?1Yh5uRYO8y87*I$XFj;P`fPm(8(B^vCiM>X_2||<376>M4(AJ zPfUCxxet3=uIWv;Is)_c`|70#yE^6CtxP<=^145*Vg;-fAingW$6-`2-c2$r-%N?H zZ2*efRYTZIw2JB9)$7%8tsyEEBIHPymGuTbyF$ViGe$h4Wgs4xZP$t8rMo?P*BISK zul1YHZ)H2vnS#^y@^cP<`>naI&sT?y9gNi&H@KP5E2#xH0ZmDp!ZuWgt1=&7Ke<F1 znF++N+fh+R=OiA=zLneV(y(7bv87~V)_oGCxW2hu0IT$7r>UTcx?8m|gXG?J_LA{t zC8{iZsRf(6nuJyYpMhD|nWVD7(en+|&6jg6y~>I|_pe;Pn(EF9w~oyUPgbSW!ba$# z9IA$sdv^%;%Z7I3*h2I@X@v!%coZM&JcrNGS_S)#gOsgLJa*qs6WR_ANW4R4n;laM z+<8^}e_T=X2RsRFO4rhdR3_r!9e|QAxREdWko}Q<k^Tn)(1Yn2=)mAQFnt_M52=3| z2{+V&!H_W6{NWj~e*nbr%fSJ0{~gG)^Q=1nH2$-J98C0&BKr_Y|6ufyuro+K#J`su T{Ve?DfB~Q{U@dCQ2{--%6Z0WK literal 0 HcmV?d00001 diff --git a/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..0778b841f126a4fbccd94eaffa1e7a90a83b0215 GIT binary patch literal 1518 zcmZ{kdpOez7{`BdOXiwzDzToV)y6JO$B0};6Dql6sqALWY=$kQ4#f#`Qbvl*CB$MK zSqi6%I?8coB$`>)#bvVMkS@~V>^$dr&hz-=JkR^S-}mx--uJ&ZXJ3$?(W<qp001z; z?e+=QXzV|}Qb!Z*<H~(CVn^B?90&j>HUmI<CIBpGTIp{AfCC2rRTKbVE(3rStF&#u zn`W?rxW~^2Sjsxz{XkRcvvGk~{YfotZG9W{o{e(=pz{pp;~A1HpDJM-3#F`YPn*Li zl)GV^+mST^;bF0@NGq4V=7jwj{@@cC{@E24nKvuk>pWji)aizieJ*5X;=Bhay2dul zwG!uHHbba%lrUWGG+*k^`c|6ws>kKa^mJsIw>qsiOZ2UDqHL$f;)I*iQlh7+&N7=% zE67*A>#fQpa$5>0P@>}~=&7H>)b_rIx0v5UT8eGfQ&#?dQ~huv1hqHGkNW7uePTBj z(xfxgyGmgbbe1!K;#U_&Jej{R-sU>}#7lL#w6ZWlFD2KdP4_*db{iHVQtvv=%sGgZ zNjjj-Ake~4!y$VfV4Gq`agTGFlp4@&J_d-}U(*#{VC1}vBy4TF=rxdhos%7)={P&M z+}-;Oi=wvdDi=d1)(Ibf+!PW+avFzb&r5^LuIBx;4pu&#ITNu$U@KrnMpI|E^7r=^ z?Y*jNf*9YpW~?<cH7oYBV5oP;4sbifO6bcJ$#u6-onFP~<(7`a;|{E?yqoXtfi-k) z1+D08pl;3ON8Y5(8akQpW2{nF>%PLo@NeJx^H|ckn0#hV@&}vnv*E3w%_%?6>ST!R zF1BHbLzA*0DpW{5P9eqi3C+*-x5oz<8Bz?YC`DRfsv?5|ah>-LTRpqn<DiAZs1160 zJAWavkW-MFY60u*F_CJ-5d^|-Aw9*`UqOSSqGqa@-~xs5VWE~?h2DI0R0e6F4MNT{ zr$2>}6WS|9?*JM3u}MXDnDEN;sGPu*@>+k`DdJMgd6rf>w@&VR8)?zslm(0AsvcJ@ znu<ljdyg#AxreIpp@n#pHSCUCkk47N6))r!7-c7)R?Q{s*@nS`-FmlP+ick=<cD-N z)X9lOruV^;V`~!pLh57FvIFJPl8E_rD(kfigRDqF=xjYV3~U5Fw=kXU(Q)I2)bT*) z2F~_@n;pU1_V;0axMcmk-<Fs*B)t)gpmSYG*8|PC(y4e@PYSFEU-YJlF?G_Prjy4q z0S+T#&YO|Z4jZphW{g^`txIR{Q1nao<%%z|TM8zhLC{u6YxUWCWV6{B2Y-_Y@9i8p zIp(`rLKFz=MJsvqRHcDRD|t|r>~12zt<IsVeyuvmJJMA=bI-fGr_N>CagcM0{FQIt zM%g&@M%FhNnk&RH&`Y0xLZDqOU76@Cp+%tmpt-M@icc5US2@$KAHimj>S@N08{AJm z`tI0OVoCpA?uo7)K|Wc%o>0Z9LArlh^fME6Ij>jJIurS^qjx_E(*3y+LB@lVHN~US zAfRjla2XIu@T8at=HMGbAztaw;<e!@ekv_GpIHh2wi;x7DOp1JOYiIZ++y<*^;|cl zzl62RcFgd|wLiEo0}GpSPb@amQu{m}^g)!qyw$T7-XBpsJC9*pCDXpZD)JRia`$6G zxh79?TZ3BJbmR`NE47S!?n8@aeRG-Of;J)rH{~X7)W<U#p2N)dno+6tXo;t#s;JSS zKwda{yf{XoNTTX;a7(dLXt)6Em(*EMkXrt7Q%%p@S?`jEwdCL~eYNsOd|qP7&cf<< zjOc}<JY~ESJ)#RXW*&8hurOJ1F>Dd{ZOL-^D=~fT(Sd02zY@@OTJ!Mi+1P_@GJ#FO zkP;{w0g!Mc8U{ze;HVHd5`)@~K{#)N!!dBU(sUHG3}D2OY0)YF4_pd7)TjZr{C9y( kV^9*=1O{svgTlafV302V9<drW7|}2Q4jbfi!z=2{-waEq(f|Me literal 0 HcmV?d00001 diff --git a/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..318914c59e86df6fe1f898925bdbb089682b5461 GIT binary patch literal 3110 zcmb7`X*3jU8^@<8%AR!?m1LQSF(Wb<J6S7Rwi#rLY0CD9&|?YN21ByUP?nHwEHhb? zBt{rgjG3shj4~m5vW8dhbIyCt^WpvQe7LXwxv%^D&UK&vhx`5~U$HUcJ1%(~008ir zUoy5mP}=Xs&3RB|!SlWca@y;Xtu+8}R~`U}xeowrAGBh=004hL0Dwgg005o`0Eh?T z+pg*y92~xGX=V)APs$kVI@ocAnp>N2eLcj%!6p66^2`qafakcmv4MR!eTfhmDEdLV zPftc>&IclRg=i!4?6e2TkzHM)=pZCo?9c!&B{^u1xg04YTy<q{KDa	~P-ja}XlY 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 literal 0 HcmV?d00001 diff --git a/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..b1165abe85ed60d39f44a52b3bccb09a7c8f50ea GIT binary patch literal 4880 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 A&;S4c literal 0 HcmV?d00001 diff --git a/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png b/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..ea11a01d31ea2f0a00bf72409a2fe79103aa1186 GIT binary patch literal 6978 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 X|Jw=OGV%JI3_wFgN4ZYXI{g0tJY&B* literal 0 HcmV?d00001 From 82b65e8934f6e31ef945a13b9295c42a3c207218 Mon Sep 17 00:00:00 2001 From: cyan <cyjan@mrcyjanek.net> Date: Sat, 11 Jan 2025 21:35:45 +0100 Subject: [PATCH 4/9] Fix normal wallets showing export outputs QR code (#1952) --- cw_monero/lib/monero_wallet.dart | 3 + ios/Podfile.lock | 100 +++++------------- linux/flutter/generated_plugins.cmake | 1 - macos/Flutter/GeneratedPluginRegistrant.swift | 2 - windows/flutter/generated_plugins.cmake | 1 - 5 files changed, 28 insertions(+), 79 deletions(-) diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index b46e8dd10..af943b9e1 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -265,6 +265,9 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance, } bool needExportOutputs(int amount) { + if (int.tryParse(monero.Wallet_secretSpendKey(wptr!)) != 0) { + return false; + } // viewOnlyBalance - balance that we can spend // TODO(mrcyjanek): remove hasUnknownKeyImages when we cleanup coin control return (monero.Wallet_viewOnlyBalance(wptr!, diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9e2a8507a..5b80a86e8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3,38 +3,6 @@ PODS: - Flutter - ReachabilitySwift - CryptoSwift (1.8.3) - - cw_haven (0.0.1): - - cw_haven/Boost (= 0.0.1) - - cw_haven/Haven (= 0.0.1) - - cw_haven/OpenSSL (= 0.0.1) - - cw_haven/Sodium (= 0.0.1) - - cw_shared_external - - Flutter - - cw_haven/Boost (0.0.1): - - cw_shared_external - - Flutter - - cw_haven/Haven (0.0.1): - - cw_shared_external - - Flutter - - cw_haven/OpenSSL (0.0.1): - - cw_shared_external - - Flutter - - cw_haven/Sodium (0.0.1): - - cw_shared_external - - Flutter - - cw_mweb (0.0.1): - - Flutter - - cw_shared_external (0.0.1): - - cw_shared_external/Boost (= 0.0.1) - - cw_shared_external/OpenSSL (= 0.0.1) - - cw_shared_external/Sodium (= 0.0.1) - - Flutter - - cw_shared_external/Boost (0.0.1): - - Flutter - - cw_shared_external/OpenSSL (0.0.1): - - Flutter - - cw_shared_external/Sodium (0.0.1): - - Flutter - device_display_brightness (0.0.1): - Flutter - device_info_plus (0.0.1): @@ -117,8 +85,6 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - sp_scanner (0.0.1): - - Flutter - SwiftyGif (5.4.5) - Toast (4.1.1) - uni_links (0.0.1): @@ -136,9 +102,6 @@ PODS: DEPENDENCIES: - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - CryptoSwift - - cw_haven (from `.symlinks/plugins/cw_haven/ios`) - - cw_mweb (from `.symlinks/plugins/cw_mweb/ios`) - - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) @@ -158,7 +121,6 @@ DEPENDENCIES: - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - sp_scanner (from `.symlinks/plugins/sp_scanner/ios`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - universal_ble (from `.symlinks/plugins/universal_ble/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) @@ -179,12 +141,6 @@ SPEC REPOS: EXTERNAL SOURCES: connectivity_plus: :path: ".symlinks/plugins/connectivity_plus/ios" - cw_haven: - :path: ".symlinks/plugins/cw_haven/ios" - cw_mweb: - :path: ".symlinks/plugins/cw_mweb/ios" - cw_shared_external: - :path: ".symlinks/plugins/cw_shared_external/ios" device_display_brightness: :path: ".symlinks/plugins/device_display_brightness/ios" device_info_plus: @@ -223,8 +179,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - sp_scanner: - :path: ".symlinks/plugins/sp_scanner/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" universal_ble: @@ -237,44 +191,40 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/workmanager/ios" SPEC CHECKSUMS: - connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d + connectivity_plus: 481668c94744c30c53b8895afb39159d1e619bdf CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483 - cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a - cw_mweb: 87af74f9659fed0c1a2cbfb44413f1070e79e3ae - cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 - device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 - device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 - devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926 + device_display_brightness: 04374ebd653619292c1d996f00f42877ea19f17f + device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 + devicelocale: bd64aa714485a8afdaded0892c1e7d5b7f680cf8 DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - fast_scanner: 44c00940355a51258cd6c2085734193cd23d95bc - file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de + fast_scanner: 2cb1ad3e69e645e9980fb4961396ce5804caa3e3 + file_picker: 07c75322ede1d47ec9bb4ac82b27c94d3598251a Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 - flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb - flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 - flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be - fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c - in_app_review: a31b5257259646ea78e0e35fc914979b0031d011 - integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 + flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 + flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f + flutter_mailer: 3a8cd4f36c960fb04528d5471097270c19fec1c4 + flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418 + fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038 + in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457 + integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + permission_handler_apple: 3787117e48f80715ff04a3830ca039283d6a4f29 ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 - sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 - share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12 + sensitive_clipboard: 161e9abc3d56b3131309d8a321eb4690a803c16b + share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e - uni_links: d97da20c7701486ba192624d99bffaaffcfc298a - universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56 - workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 + uni_links: ed8c961e47ed9ce42b6d91e1de8049e38a4b3152 + universal_ble: ff19787898040d721109c6324472e5dd4bc86adc + url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49 + workmanager: 01be2de7f184bd15de93a1812936a2b7f42ef07e PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index f52be7481..4b9eb3b2d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -10,7 +10,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - sp_scanner ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 42b9fa84c..52b44e53e 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,6 @@ import FlutterMacOS import Foundation import connectivity_plus -import cw_mweb import device_info_plus import devicelocale import fast_scanner @@ -24,7 +23,6 @@ import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) - CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index e0f2c11c0..f8f89611c 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -14,7 +14,6 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - sp_scanner ) set(PLUGIN_BUNDLED_LIBRARIES) From e42d49f3edd5082f88cf3301486373215eab00bf Mon Sep 17 00:00:00 2001 From: cyan <cyjan@mrcyjanek.net> Date: Sat, 11 Jan 2025 21:36:41 +0100 Subject: [PATCH 5/9] fix print in default_settings_migration (#1953) * fix print in default_settings_migration * Update lib/entities/default_settings_migration.dart [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> --- lib/entities/default_settings_migration.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index abcdda4c0..049bfa15c 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -394,9 +394,6 @@ Future<void> _updateNode({ bool? useSSL, }) async { for (Node node in nodes.values) { - print("@@@@@@@@@@@@@"); - print(node.uriRaw); - print(node.uri); if (node.uriRaw == currentUri) { if (newUri != null) { node.uriRaw = newUri; From 206c7159c21e63c67430f8063f58a5fb5b6a3650 Mon Sep 17 00:00:00 2001 From: OmarHatem <omarh.ismail1@gmail.com> Date: Mon, 13 Jan 2025 13:06:43 +0200 Subject: [PATCH 6/9] minor fix [skip ci] --- ios/Podfile.lock | 100 +++++++++++++----- lib/src/screens/send/send_page.dart | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + windows/flutter/generated_plugins.cmake | 1 + 5 files changed, 83 insertions(+), 25 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 5b80a86e8..9e2a8507a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3,6 +3,38 @@ PODS: - Flutter - ReachabilitySwift - CryptoSwift (1.8.3) + - cw_haven (0.0.1): + - cw_haven/Boost (= 0.0.1) + - cw_haven/Haven (= 0.0.1) + - cw_haven/OpenSSL (= 0.0.1) + - cw_haven/Sodium (= 0.0.1) + - cw_shared_external + - Flutter + - cw_haven/Boost (0.0.1): + - cw_shared_external + - Flutter + - cw_haven/Haven (0.0.1): + - cw_shared_external + - Flutter + - cw_haven/OpenSSL (0.0.1): + - cw_shared_external + - Flutter + - cw_haven/Sodium (0.0.1): + - cw_shared_external + - Flutter + - cw_mweb (0.0.1): + - Flutter + - cw_shared_external (0.0.1): + - cw_shared_external/Boost (= 0.0.1) + - cw_shared_external/OpenSSL (= 0.0.1) + - cw_shared_external/Sodium (= 0.0.1) + - Flutter + - cw_shared_external/Boost (0.0.1): + - Flutter + - cw_shared_external/OpenSSL (0.0.1): + - Flutter + - cw_shared_external/Sodium (0.0.1): + - Flutter - device_display_brightness (0.0.1): - Flutter - device_info_plus (0.0.1): @@ -85,6 +117,8 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - sp_scanner (0.0.1): + - Flutter - SwiftyGif (5.4.5) - Toast (4.1.1) - uni_links (0.0.1): @@ -102,6 +136,9 @@ PODS: DEPENDENCIES: - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - CryptoSwift + - cw_haven (from `.symlinks/plugins/cw_haven/ios`) + - cw_mweb (from `.symlinks/plugins/cw_mweb/ios`) + - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) @@ -121,6 +158,7 @@ DEPENDENCIES: - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sp_scanner (from `.symlinks/plugins/sp_scanner/ios`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - universal_ble (from `.symlinks/plugins/universal_ble/darwin`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) @@ -141,6 +179,12 @@ SPEC REPOS: EXTERNAL SOURCES: connectivity_plus: :path: ".symlinks/plugins/connectivity_plus/ios" + cw_haven: + :path: ".symlinks/plugins/cw_haven/ios" + cw_mweb: + :path: ".symlinks/plugins/cw_mweb/ios" + cw_shared_external: + :path: ".symlinks/plugins/cw_shared_external/ios" device_display_brightness: :path: ".symlinks/plugins/device_display_brightness/ios" device_info_plus: @@ -179,6 +223,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sp_scanner: + :path: ".symlinks/plugins/sp_scanner/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" universal_ble: @@ -191,40 +237,44 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/workmanager/ios" SPEC CHECKSUMS: - connectivity_plus: 481668c94744c30c53b8895afb39159d1e619bdf + connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483 - device_display_brightness: 04374ebd653619292c1d996f00f42877ea19f17f - device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 - devicelocale: bd64aa714485a8afdaded0892c1e7d5b7f680cf8 + cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a + cw_mweb: 87af74f9659fed0c1a2cbfb44413f1070e79e3ae + cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 + device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 + device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 + devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926 DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - fast_scanner: 2cb1ad3e69e645e9980fb4961396ce5804caa3e3 - file_picker: 07c75322ede1d47ec9bb4ac82b27c94d3598251a + fast_scanner: 44c00940355a51258cd6c2085734193cd23d95bc + file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 - flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f - flutter_mailer: 3a8cd4f36c960fb04528d5471097270c19fec1c4 - flutter_secure_storage: 2c2ff13db9e0a5647389bff88b0ecac56e3f3418 - fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038 - in_app_review: 5596fe56fab799e8edb3561c03d053363ab13457 - integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e + flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 + flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb + flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 + flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be + fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c + in_app_review: a31b5257259646ea78e0e35fc914979b0031d011 + integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573 OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 - permission_handler_apple: 3787117e48f80715ff04a3830ca039283d6a4f29 + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 - sensitive_clipboard: 161e9abc3d56b3131309d8a321eb4690a803c16b - share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a - shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 + share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sp_scanner: eaa617fa827396b967116b7f1f43549ca62e9a12 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e - uni_links: ed8c961e47ed9ce42b6d91e1de8049e38a4b3152 - universal_ble: ff19787898040d721109c6324472e5dd4bc86adc - url_launcher_ios: 694010445543906933d732453a59da0a173ae33d - wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49 - workmanager: 01be2de7f184bd15de93a1812936a2b7f42ef07e + uni_links: d97da20c7701486ba192624d99bffaaffcfc298a + universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56 + workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 PODFILE CHECKSUM: e448f662d4c41f0c0b1ccbb78afd57dbf895a597 -COCOAPODS: 1.16.2 +COCOAPODS: 1.15.2 diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index a52bd11e9..2d64c55a3 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -525,6 +525,10 @@ class SendPage extends BasePage { if (state is TransactionCommitted) { WidgetsBinding.instance.addPostFrameCallback((_) async { + if (!context.mounted) { + return; + } + final successMessage = S.of(context).send_success( sendViewModel.selectedCryptoCurrency.toString()); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 4b9eb3b2d..f52be7481 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + sp_scanner ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 52b44e53e..42b9fa84c 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,6 +6,7 @@ import FlutterMacOS import Foundation import connectivity_plus +import cw_mweb import device_info_plus import devicelocale import fast_scanner @@ -23,6 +24,7 @@ import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index f8f89611c..e0f2c11c0 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -14,6 +14,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + sp_scanner ) set(PLUGIN_BUNDLED_LIBRARIES) From 80b116b8ae31bb86830aca1fa50192919a0bb2af Mon Sep 17 00:00:00 2001 From: hidewrong <hidewrong@outlook.com> Date: Tue, 14 Jan 2025 22:34:53 +0800 Subject: [PATCH 7/9] chore: fix some typos for build-guide-*.md (#1958) Signed-off-by: hidewrong <hidewrong@outlook.com> --- build-guide-linux.md | 2 +- build-guide-win.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build-guide-linux.md b/build-guide-linux.md index 99c2ed0c8..df5f0f601 100644 --- a/build-guide-linux.md +++ b/build-guide-linux.md @@ -115,7 +115,7 @@ Install Flutter package dependencies with this command: > `$ ./cakewallet.sh` > and back to project root directory: > `$ cd ../..` -> and fetch dependecies again +> and fetch dependencies again > `$ flutter pub get` Your CakeWallet binary will be built with some specific keys for iterate with 3rd party services. You may generate these secret keys placeholders with the following command: diff --git a/build-guide-win.md b/build-guide-win.md index 6ace961af..8cfd02c4c 100644 --- a/build-guide-win.md +++ b/build-guide-win.md @@ -16,14 +16,14 @@ These steps will help you configure and execute a build of CakeWallet from its s ### 1. Installing Package Dependencies For build CakeWallet windows application from sources you will be needed to have: -> [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windwos`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`. +> [Install Flutter]Follow installation guide (https://docs.flutter.dev/get-started/install/windows) and install do not miss to dev tools (install https://docs.flutter.dev/get-started/install/windows/desktop#development-tools) which are required for windows desktop development (need to install Git for Windows and Visual Studio 2022). Then install `Desktop development with C++` packages via GUI Visual Studio 2022, or Visual Studio Build Tools 2022 including: `C++ Build Tools core features`, `C++ 2022 Redistributable Update`, `C++ core desktop features`, `MVC v143 - VS 2022 C++ x64/x86 build tools`, `C++ CMake tools for Windows`, `Testing tools core features - Build Tools`, `C++ AddressSanitizer`. > [Install WSL] for building monero dependencies need to install Windows WSL (https://learn.microsoft.com/en-us/windows/wsl/install) and required packages for WSL (Ubuntu): `$ sudo apt update ` `$ sudo apt build-essential cmake gcc-mingw-w64 g++-mingw-w64 autoconf libtool pkg-config` ### 2. Pull CakeWallet source code -You can downlaod CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command: +You can download CakeWallet source code from our [GitHub repository](github.com/cake-tech/cake_wallet) via git by following next command: `$ git clone https://github.com/cake-tech/cake_wallet.git --branch MrCyjaneK-cyjan-monerodart` OR you can download it as [Zip archive](https://github.com/cake-tech/cake_wallet/archive/refs/heads/MrCyjaneK-cyjan-monerodart.zip) From 3e10023e187ec098de80ee2c984401ef2ef664b4 Mon Sep 17 00:00:00 2001 From: cyan <cyjan@mrcyjanek.net> Date: Wed, 15 Jan 2025 12:09:59 +0100 Subject: [PATCH 8/9] CW-827 CI/CD update (#1948) * CI update - use existing build outputs in build_monero_all.sh - update $HOME, fix gh actions - add secrets earlier in the runtime (potentially speed up 'Build generated code' step) - add windows dockerfile - add linux/android dockerfile - update android/linux ci script * [skip slack] [run tests] Run tests on CI, fix tests * [skip slack] [run tests] force enable kvm in android * [skip slack] [run tests] remove inexisting flag * [run tests] [skip slack] update tests * add extra dependencies [skip ci] * [skip slack] [run tests] Add secrets * [skip slack] [run tests] Timeout test cases, continue on error * [skip slack] [run tests] Xvfb fix, timeout fix * [skip slack] [run tests] Start dbus to clean up the logs, use SIGKILL * [skip slack] [run tests] Enable network manager * [skip slack] [run tests] Screen record test, resize screen * [skip slack] [run tests] Improve status report for tests * [skip slack] [run tests] Increase framerate * [skip slack] [run tests] Remove test that I am unable to fix locally easily from CI * [skip slack] [run tests] Simplify ffmpeg command * [skip slack] [run tests] Increase timeout, add comment * [skip slack] Update dockerfile, migrate from mrcyjanek to cake-tech for the ghcr org * Update lib/entities/default_settings_migration.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> --- .github/workflows/cache_dependencies.yml | 84 ---- .github/workflows/pr_test_build_android.yml | 412 +++++++++--------- .github/workflows/pr_test_build_linux.yml | 373 +++++++++------- cw_monero/lib/api/wallet.dart | 4 +- .../components/common_test_cases.dart | 5 + .../components/common_test_flows.dart | 34 +- integration_test/funds_related_tests.dart | 5 + integration_test/robots/auth_page_robot.dart | 5 + .../robots/pin_code_widget_robot.dart | 14 + .../restore_from_seed_or_key_robot.dart | 20 +- integration_test/robots/send_page_robot.dart | 35 +- .../robots/wallet_seed_page_robot.dart | 16 +- .../test_suites/confirm_seeds_flow_test.dart | 8 + .../test_suites/exchange_flow_test.dart | 4 + ...estore_wallet_through_seeds_flow_test.dart | 3 + integration_test_runner.sh | 5 + .../screens/new_wallet/new_wallet_page.dart | 2 + .../wallet_restore_from_keys_form.dart | 2 + .../wallet_restore_from_seed_form.dart | 2 + .../wallet_unlock/wallet_unlock_page.dart | 2 + linux/my_application.cc | 7 +- model_generator.sh | 34 +- scripts/android/.gitignore | 1 + scripts/android/build_monero_all.sh | 60 +-- scripts/android/build_mwebd.sh | 5 +- scripts/linux/Dockerfile.linux | 148 +++++++ scripts/linux/build_monero_all.sh | 18 +- scripts/prepare_moneroc.sh | 4 +- scripts/windows/.gitignore | 1 + scripts/windows/Dockerfile.windows | 68 +++ scripts/windows/ci_entrypoint.ps1 | 5 + scripts/windows/ci_register.ps1 | 30 ++ 32 files changed, 862 insertions(+), 554 deletions(-) delete mode 100644 .github/workflows/cache_dependencies.yml create mode 100644 scripts/android/.gitignore create mode 100644 scripts/linux/Dockerfile.linux create mode 100644 scripts/windows/.gitignore create mode 100644 scripts/windows/Dockerfile.windows create mode 100644 scripts/windows/ci_entrypoint.ps1 create mode 100644 scripts/windows/ci_register.ps1 diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml deleted file mode 100644 index cb2afa396..000000000 --- a/.github/workflows/cache_dependencies.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: Cache Dependencies - -on: - workflow_dispatch: - push: - branches: [ main ] - -jobs: - test: - - runs-on: ubuntu-20.04 - - steps: - - name: Free Disk Space (Ubuntu) - uses: insightsengineering/disk-space-reclaimer@v1 - with: - tools-cache: true - android: false - dotnet: true - haskell: true - large-packages: true - swap-storage: true - docker-images: true - - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 - with: - distribution: "temurin" - java-version: "17" - - name: Configure placeholder git details - run: | - git config --global user.email "CI@cakewallet.com" - git config --global user.name "Cake Github Actions" - - name: Flutter action - uses: subosito/flutter-action@v1 - with: - flutter-version: "3.24.4" - channel: stable - - - name: Install package dependencies - run: sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang - - - name: Execute Build and Setup Commands - run: | - sudo mkdir -p /opt/android - sudo chown $USER /opt/android - cd /opt/android - -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - cargo install cargo-ndk - git clone https://github.com/cake-tech/cake_wallet.git --branch main - cd cake_wallet/scripts/android/ - ./install_ndk.sh - source ./app_env.sh cakewallet - chmod +x pubspec_gen.sh - ./app_config.sh - - - name: Cache Externals - id: cache-externals - uses: actions/cache@v3 - with: - path: | - /opt/android/cake_wallet/cw_haven/android/.cxx - /opt/android/cake_wallet/scripts/monero_c/release - key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }} - - - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} - name: Generate Externals - run: | - cd /opt/android/cake_wallet/scripts/android/ - source ./app_env.sh cakewallet - ./build_monero_all.sh - - - name: Cache Keystore - id: cache-keystore - uses: actions/cache@v3 - with: - path: /opt/android/cake_wallet/android/app - key: keystore - - - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} - name: Generate KeyStore - run: | - cd /opt/android/cake_wallet/android/app - keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index cdd0e40b4..2a7eec5c9 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -1,169 +1,93 @@ -name: PR Test Build +name: Cake Wallet Android -on: - pull_request: - branches: [main] - workflow_dispatch: - inputs: - branch: - description: "Branch name to build" - required: true - default: "main" +on: [push] +defaults: + run: + shell: bash jobs: PR_test_build: - runs-on: ubuntu-20.04 + runs-on: linux-amd64 + container: + image: ghcr.io/cake-tech/cake_wallet:main-linux + env: + STORE_PASS: test@cake_wallet + KEY_PASS: test@cake_wallet + MONEROC_CACHE_DIR_ROOT: /opt/generic_cache + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + ANDROID_AVD_HOME: /root/.android/avd + volumes: + - /opt/cw_cache_android/root/.cache:/root/.cache + - /opt/cw_cache_android/root/.android/avd/:/root/.android/avd + - /opt/cw_cache_android/root/.ccache:/root/.ccache + - /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache + - /opt/cw_cache_android/root/.gradle/:/root/.gradle + - /opt/cw_cache_android/root/.android/:/root/.android + - /opt/cw_cache_android/root/go/pkg:/root/go/pkg + - /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache + - /dev/kvm:/dev/kvm strategy: matrix: api-level: [29] - env: - STORE_PASS: test@cake_wallet - KEY_PASS: test@cake_wallet - PR_NUMBER: ${{ github.event.number }} steps: - - name: is pr - if: github.event_name == 'pull_request' - run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV - - - name: is not pr - if: github.event_name != 'pull_request' - run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENV - - - name: Free Disk Space (Ubuntu) - uses: insightsengineering/disk-space-reclaimer@v1 - with: - tools-cache: true - android: false - dotnet: true - haskell: true - large-packages: true - swap-storage: true - docker-images: true - - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 - with: - distribution: "temurin" - java-version: "17" - - name: Configure placeholder git details + - name: Fix github actions messing up $HOME... + run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV' + - uses: actions/checkout@v4 + - name: configure git run: | - git config --global user.email "CI@cakewallet.com" - git config --global user.name "Cake Github Actions" - - name: Flutter action - uses: subosito/flutter-action@v1 - with: - flutter-version: "3.24.0" - channel: stable - - - name: Install package dependencies - run: | - sudo apt update - sudo apt-get install -y curl unzip automake build-essential file pkg-config git python libtool libtinfo5 cmake clang - - - - name: Clone Repo - run: | - sudo mkdir -p /opt/android - sudo chown $USER /opt/android - cd /opt/android - git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }} - -# - name: Cache Keystore -# id: cache-keystore -# uses: actions/cache@v3 -# with: -# path: /opt/android/cake_wallet/android/app -# key: keystore -# -# - if: ${{ steps.cache-keystore.outputs.cache-hit != 'true' }} - - name: Generate KeyStore - run: | - cd /opt/android/cake_wallet/android/app - keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS - - - name: Execute Build and Setup Commands - run: | - cd /opt/android - -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - cargo install cargo-ndk - cd cake_wallet/scripts/android/ - ./install_ndk.sh - source ./app_env.sh cakewallet - chmod +x pubspec_gen.sh - ./app_config.sh - - - name: Cache Externals - id: cache-externals - uses: actions/cache@v3 - with: - path: | - /opt/android/cake_wallet/cw_haven/android/.cxx - /opt/android/cake_wallet/scripts/monero_c/release - key: ${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }} - - - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} - name: Generate Externals - run: | - cd /opt/android/cake_wallet/scripts/android/ - source ./app_env.sh cakewallet - ./build_monero_all.sh - - - name: Install Flutter dependencies - run: | - cd /opt/android/cake_wallet - flutter pub get - - - - name: Install go and gomobile - run: | - # install go > 1.23: - wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz - sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz - export PATH=$PATH:/usr/local/go/bin - export PATH=$PATH:~/go/bin - go install golang.org/x/mobile/cmd/gomobile@latest - gomobile init - - - name: Build mwebd - run: | - # paths are reset after each step, so we need to set them again: - export PATH=$PATH:/usr/local/go/bin - export PATH=$PATH:~/go/bin - cd /opt/android/cake_wallet/scripts/android/ - ./build_mwebd.sh --dont-install - - - name: Generate key properties - run: | - cd /opt/android/cake_wallet - dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS - - - name: Generate localization - run: | - cd /opt/android/cake_wallet - dart run tool/generate_localization.dart - - - name: Build generated code - run: | - cd /opt/android/cake_wallet - ./model_generator.sh - + git config --global user.email "ci@cakewallet.com" + git config --global user.name "CakeWallet CI" - name: Add secrets run: | - cd /opt/android/cake_wallet touch lib/.secrets.g.dart touch cw_evm/lib/.secrets.g.dart touch cw_solana/lib/.secrets.g.dart touch cw_core/lib/.secrets.g.dart touch cw_nano/lib/.secrets.g.dart touch cw_tron/lib/.secrets.g.dart - echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart - echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart - echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart - echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart - echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart - echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart - echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + if [[ "x${{ secrets.SALT }}" == "x" ]]; + then + echo "const salt = '954f787f12622067f7e548d9450c3832';" > lib/.secrets.g.dart + else + echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart + fi + if [[ "x${{ secrets.KEY_CHAIN_SALT }}" == "x" ]]; + then + echo "const keychainSalt = '2d2beba777dbf7dff7013b7a';" >> lib/.secrets.g.dart + else + echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.KEY }}" == "x" ]]; + then + echo "const key = '638e98820ec10a2945e968435c9397a3';" >> lib/.secrets.g.dart + else + echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.WALLET_SALT }}" == "x" ]]; + then + echo "const walletSalt = '8f7f1b70';" >> lib/.secrets.g.dart + else + echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.SHORT_KEY }}" == "x" ]]; + then + echo "const shortKey = '653f270c2c152bc7ec864afe';" >> lib/.secrets.g.dart + else + echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.BACKUP_SALT }}" == "x" ]]; + then + echo "const backupSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart + else + echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.BACKUP_KEY_CHAIN_SALT }}" == "x" ]]; + then + echo "const backupKeychainSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart + else + echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + fi echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart echo "const changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart @@ -213,86 +137,152 @@ jobs: echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart + # for tests + echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const litecoinTestWalletSeeds = '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const bitcoinCashTestWalletSeeds = '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const nanoTestWalletSeeds = '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const bitcoinTestWalletReceiveAddress = '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const ethereumTestWalletReceiveAddress = '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const litecoinTestWalletReceiveAddress = '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const polygonTestWalletReceiveAddress = '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const solanaTestWalletReceiveAddress = '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const tronTestWalletReceiveAddress = '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const moneroTestWalletBlockHeight = '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart + - name: prepare monero_c and cache + run: | + export MONEROC_HASH=$(cat scripts/prepare_moneroc.sh | grep 'git checkout' | xargs | awk '{ print $3 }') + echo MONEROC_HASH=$MONEROC_HASH >> /etc/environment + mkdir -p "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c" + pushd scripts + ln -s "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c" + ./prepare_moneroc.sh + popd + pushd scripts/monero_c + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" || true + + rm -rf "$PWD/contrib/depends/built" "$PWD/monero/contrib/depends/built" "$PWD/wownero/contrib/depends/built" + rm -rf "$PWD/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources" + mkdir -p contrib/depends || true + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" "$PWD/contrib/depends/built" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" "$PWD/monero/contrib/depends/built" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" "$PWD/wownero/contrib/depends/built" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" "$PWD/contrib/depends/sources" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources" + popd + + - name: Generate KeyStore + run: | + pushd /opt/generic_cache + if [[ ! -f key.jks ]]; + then + keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias testKey -noprompt -dname "CN=CakeWallet, OU=CakeWallet, O=CakeWallet, L=Florida, S=America, C=USA" -storepass $STORE_PASS -keypass $KEY_PASS + else + echo "$PWD/key.jks exist, not generating" + fi + popd + cp /opt/generic_cache/key.jks android/app + + - name: Execute Build and Setup Commands + run: | + pushd scripts/android + source ./app_env.sh cakewallet + ./app_config.sh + popd + + - name: Build monero_c + run: | + pushd scripts/android/ + source ./app_env.sh cakewallet + ./build_monero_all.sh + popd + + - name: Install Flutter dependencies + run: | + flutter pub get + + - name: Build mwebd + run: | + set -x -e + export MWEBD_HASH=$(cat scripts/android/build_mwebd.sh | grep 'git reset --hard' | xargs | awk '{ print $4 }') + echo MWEBD_HASH=$MWEBD_HASH >> /etc/environment + pushd scripts/android + gomobile init; + ./build_mwebd.sh --dont-install + popd + + - name: Build generated code + run: | + ./model_generator.sh async + + - name: Generate key properties + run: | + dart run tool/generate_android_key_properties.dart keyAlias=testKey storeFile=key.jks storePassword=$STORE_PASS keyPassword=$KEY_PASS + + - name: Generate localization + run: | + dart run tool/generate_localization.dart - name: Rename app run: | - echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties + sanitized_branch_name=${BRANCH_NAME#origin/} # Remove 'origin/' prefix if it exists + sanitized_branch_name=${sanitized_branch_name:0:16} # Take only the first 16 characters + sanitized_branch_name=$(echo "$sanitized_branch_name" | tr '[:upper:]' '[:lower:]') # Convert to lowercase + sanitized_branch_name=$(echo "$sanitized_branch_name" | sed 's/[^a-z0-9]//g') # Remove all special characters - # Step 3: Download previous build number - - name: Download previous build number - id: download-build-number - run: | - # Download the artifact if it exists - if [[ ! -f build_number.txt ]]; then - echo "1" > build_number.txt - fi - - # Step 4: Read and Increment Build Number - - name: Increment Build Number - id: increment-build-number - run: | - # Read current build number from file - BUILD_NUMBER=$(cat build_number.txt) - BUILD_NUMBER=$((BUILD_NUMBER + 1)) - echo "New build number: $BUILD_NUMBER" - - # Save the incremented build number - echo "$BUILD_NUMBER" > build_number.txt - - # Export the build number to use in later steps - echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV - - # Step 5: Update pubspec.yaml with new build number - - name: Update build number - run: | - cd /opt/android/cake_wallet - sed -i "s/^version: .*/version: 1.0.$BUILD_NUMBER/" pubspec.yaml + echo -e "id=com.cakewallet.test_${sanitized_branch_name}\nname=${BRANCH_NAME}" > android/app.properties - name: Build run: | - cd /opt/android/cake_wallet flutter build apk --release --split-per-abi - # - name: Push to App Center - # run: | - # echo 'Installing App Center CLI tools' - # npm install -g appcenter-cli - # echo "Publishing test to App Center" - # appcenter distribute release \ - # --group "Testers" \ - # --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ - # --release-notes ${{ env.BRANCH_NAME }} \ - # --app Cake-Labs/Cake-Wallet \ - # --token ${{ secrets.APP_CENTER_TOKEN }} \ - # --quiet - - name: Rename apk file run: | - cd /opt/android/cake_wallet/build/app/outputs/flutter-apk + cd build/app/outputs/flutter-apk mkdir test-apk - cp app-arm64-v8a-release.apk test-apk/${{env.BRANCH_NAME}}.apk - cp app-x86_64-release.apk test-apk/${{env.BRANCH_NAME}}_x86.apk + cp app-arm64-v8a-release.apk test-apk/${BRANCH_NAME}.apk + cp app-x86_64-release.apk test-apk/${BRANCH_NAME}_x86.apk + cd test-apk + cp ${BRANCH_NAME}.apk ${BRANCH_NAME}_slack.apk - - name: Upload Artifact - uses: kittaakos/upload-artifact-as-is@v0 - with: - path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/ - - # Re-upload updated build number for the next run - - name: Upload updated build number - uses: actions/upload-artifact@v3 - with: - name: build_number - path: build_number.txt - - - name: Send Test APK + - name: Find APK file + id: find_apk + run: | + set -x + apk_file=$(ls build/app/outputs/flutter-apk/test-apk/*_slack.apk || exit 1) + echo "APK_FILE=$apk_file" >> $GITHUB_ENV + + - name: Upload artifact to slack + if: ${{ !contains(github.event.head_commit.message, 'skip slack') }} continue-on-error: true uses: adrey/slack-file-upload-action@1.0.5 with: token: ${{ secrets.SLACK_APP_TOKEN }} - path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk + path: ${{ env.APK_FILE }} channel: ${{ secrets.SLACK_APK_CHANNEL }} - title: "${{ env.BRANCH_NAME }}.apk" - filename: ${{ env.BRANCH_NAME }}.apk initial_comment: ${{ github.event.head_commit.message }} + - name: cleanup + run: rm -rf build/app/outputs/flutter-apk/test-apk/ + + - name: Upload Artifact to github + uses: kittaakos/upload-artifact-as-is@v0 + with: + path: ${{ github.workspace }}/build/app/outputs/flutter-apk \ No newline at end of file diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml index 891327d1e..6a29e4033 100644 --- a/.github/workflows/pr_test_build_linux.yml +++ b/.github/workflows/pr_test_build_linux.yml @@ -1,139 +1,89 @@ -name: PR Test Build linux +name: Cake Wallet Linux -on: - pull_request: - branches: [main] - workflow_dispatch: - inputs: - branch: - description: "Branch name to build" - required: true - default: "main" +on: [push] +defaults: + run: + shell: bash jobs: PR_test_build: - runs-on: ubuntu-20.04 - env: - STORE_PASS: test@cake_wallet - KEY_PASS: test@cake_wallet - PR_NUMBER: ${{ github.event.number }} + runs-on: linux-amd64 + container: + image: ghcr.io/cake-tech/cake_wallet:main-linux + env: + STORE_PASS: test@cake_wallet + KEY_PASS: test@cake_wallet + MONEROC_CACHE_DIR_ROOT: /opt/generic_cache + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + DESKTOP_FORCE_MOBILE: Y + volumes: + - /opt/cw_cache_linux/root/.cache:/root/.cache + - /opt/cw_cache_linux/root/.ccache:/root/.ccache + - /opt/cw_cache_linux/root/.pub-cache/:/root/.pub-cache + - /opt/cw_cache_linux/root/go/pkg:/root/go/pkg + - /opt/cw_cache_linux/opt/generic_cache:/opt/generic_cache + strategy: + matrix: + api-level: [29] steps: - - name: is pr - if: github.event_name == 'pull_request' - run: echo "BRANCH_NAME=${GITHUB_HEAD_REF}" >> $GITHUB_ENV - - - name: is not pr - if: github.event_name != 'pull_request' - run: echo "BRANCH_NAME=${{ github.event.inputs.branch }}" >> $GITHUB_ENVg - - - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 - with: - java-version: "17.x" - - name: Configure placeholder git details + - name: Fix github actions messing up $HOME... + run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV' + - uses: actions/checkout@v4 + - name: configure git run: | - git config --global user.email "CI@cakewallet.com" - git config --global user.name "Cake Github Actions" - - name: Flutter action - uses: subosito/flutter-action@v1 - with: - flutter-version: "3.24.0" - channel: stable - - - name: Install package dependencies - run: | - sudo apt update - sudo apt-get install -y curl unzip automake build-essential file pkg-config git python-is-python3 libtool libtinfo5 cmake clang - - - name: Install desktop dependencies - run: | - sudo apt update - sudo apt install -y ninja-build libgtk-3-dev gperf - - name: Execute Build and Setup Commands - run: | - sudo mkdir -p /opt/android - sudo chown $USER /opt/android - cd /opt/android - -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - cargo install cargo-ndk - git clone https://github.com/cake-tech/cake_wallet.git --branch ${{ env.BRANCH_NAME }} - cd scripts && ./gen_android_manifest.sh && cd .. - cd cake_wallet/scripts/android/ - source ./app_env.sh cakewallet - ./app_config.sh - cd ../../.. - cd cake_wallet/scripts/linux/ - source ./app_env.sh cakewallet - ./app_config.sh - cd ../../.. - - - name: Cache Externals - id: cache-externals - uses: actions/cache@v3 - with: - path: | - /opt/android/cake_wallet/cw_haven/android/.cxx - /opt/android/cake_wallet/scripts/monero_c/release - key: linux_${{ hashFiles('**/prepare_moneroc.sh' ,'**/build_monero_all.sh' ,'**/cache_dependencies.yml') }} - - - if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }} - name: Generate Externals - run: | - cd /opt/android/cake_wallet/scripts/linux/ - source ./app_env.sh cakewallet - ./build_monero_all.sh - - - name: Install Flutter dependencies - run: | - cd /opt/android/cake_wallet - flutter pub get - - - name: Install go and gomobile - run: | - # install go > 1.23: - wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz - sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz - export PATH=$PATH:/usr/local/go/bin - export PATH=$PATH:~/go/bin - go install golang.org/x/mobile/cmd/gomobile@latest - gomobile init - - - name: Build mwebd - run: | - # paths are reset after each step, so we need to set them again: - export PATH=$PATH:/usr/local/go/bin - export PATH=$PATH:~/go/bin - # build mwebd: - cd /opt/android/cake_wallet/scripts/android/ - ./build_mwebd.sh --dont-install - - - name: Generate localization - run: | - cd /opt/android/cake_wallet - dart run tool/generate_localization.dart - - - name: Build generated code - run: | - cd /opt/android/cake_wallet - ./model_generator.sh - + git config --global user.email "ci@cakewallet.com" + git config --global user.name "CakeWallet CI" - name: Add secrets run: | - cd /opt/android/cake_wallet touch lib/.secrets.g.dart touch cw_evm/lib/.secrets.g.dart touch cw_solana/lib/.secrets.g.dart touch cw_core/lib/.secrets.g.dart touch cw_nano/lib/.secrets.g.dart touch cw_tron/lib/.secrets.g.dart - echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart - echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart - echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart - echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart - echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart - echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart - echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + if [[ "x${{ secrets.SALT }}" == "x" ]]; + then + echo "const salt = '954f787f12622067f7e548d9450c3832';" > lib/.secrets.g.dart + else + echo "const salt = '${{ secrets.SALT }}';" > lib/.secrets.g.dart + fi + if [[ "x${{ secrets.KEY_CHAIN_SALT }}" == "x" ]]; + then + echo "const keychainSalt = '2d2beba777dbf7dff7013b7a';" >> lib/.secrets.g.dart + else + echo "const keychainSalt = '${{ secrets.KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.KEY }}" == "x" ]]; + then + echo "const key = '638e98820ec10a2945e968435c9397a3';" >> lib/.secrets.g.dart + else + echo "const key = '${{ secrets.KEY }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.WALLET_SALT }}" == "x" ]]; + then + echo "const walletSalt = '8f7f1b70';" >> lib/.secrets.g.dart + else + echo "const walletSalt = '${{ secrets.WALLET_SALT }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.SHORT_KEY }}" == "x" ]]; + then + echo "const shortKey = '653f270c2c152bc7ec864afe';" >> lib/.secrets.g.dart + else + echo "const shortKey = '${{ secrets.SHORT_KEY }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.BACKUP_SALT }}" == "x" ]]; + then + echo "const backupSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart + else + echo "const backupSalt = '${{ secrets.BACKUP_SALT }}';" >> lib/.secrets.g.dart + fi + if [[ "x${{ secrets.BACKUP_KEY_CHAIN_SALT }}" == "x" ]]; + then + echo "const backupKeychainSalt = 'bf630d24ff0b6f60';" >> lib/.secrets.g.dart + else + echo "const backupKeychainSalt = '${{ secrets.BACKUP_KEY_CHAIN_SALT }}';" >> lib/.secrets.g.dart + fi echo "const changeNowApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart echo "const changeNowApiKeyDesktop = '${{ secrets.CHANGE_NOW_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart @@ -144,8 +94,6 @@ jobs: echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart echo "const simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart - echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> lib/.secrets.g.dart - echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> lib/.secrets.g.dart echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart echo "const anypayToken = '${{ secrets.ANY_PAY_TOKEN }}';" >> lib/.secrets.g.dart echo "const ioniaClientId = '${{ secrets.IONIA_CLIENT_ID }}';" >> lib/.secrets.g.dart @@ -156,8 +104,11 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> lib/.secrets.g.dart + echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> lib/.secrets.g.dart + echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart + echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart @@ -165,7 +116,6 @@ jobs: echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart - echo "const nowNodesApiKey = '${{ secrets.EVM_NOWNODES_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart echo "const chainStackApiKey = '${{ secrets.CHAIN_STACK_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart echo "const testCakePayApiKey = '${{ secrets.TEST_CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart @@ -178,39 +128,170 @@ jobs: echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart echo "const tronNowNodesApiKey = '${{ secrets.TRON_NOW_NODES_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart echo "const meldTestApiKey = '${{ secrets.MELD_TEST_API_KEY }}';" >> lib/.secrets.g.dart - echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dar + echo "const meldTestPublicKey = '${{ secrets.MELD_TEST_PUBLIC_KEY}}';" >> lib/.secrets.g.dart echo "const letsExchangeBearerToken = '${{ secrets.LETS_EXCHANGE_TOKEN }}';" >> lib/.secrets.g.dart echo "const letsExchangeAffiliateId = '${{ secrets.LETS_EXCHANGE_AFFILIATE_ID }}';" >> lib/.secrets.g.dart echo "const stealthExBearerToken = '${{ secrets.STEALTH_EX_BEARER_TOKEN }}';" >> lib/.secrets.g.dart echo "const stealthExAdditionalFeePercent = '${{ secrets.STEALTH_EX_ADDITIONAL_FEE_PERCENT }}';" >> lib/.secrets.g.dart - - - name: Rename app + # tests + echo "const moneroTestWalletSeeds ='${{ secrets.MONERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const moneroLegacyTestWalletSeeds = '${{ secrets.MONERO_LEGACY_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const bitcoinTestWalletSeeds = '${{ secrets.BITCOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const ethereumTestWalletSeeds = '${{ secrets.ETHEREUM_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const litecoinTestWalletSeeds = '${{ secrets.LITECOIN_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const bitcoinCashTestWalletSeeds = '${{ secrets.BITCOIN_CASH_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const polygonTestWalletSeeds = '${{ secrets.POLYGON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const solanaTestWalletSeeds = '${{ secrets.SOLANA_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const tronTestWalletSeeds = '${{ secrets.TRON_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const nanoTestWalletSeeds = '${{ secrets.NANO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const wowneroTestWalletSeeds = '${{ secrets.WOWNERO_TEST_WALLET_SEEDS }}';" >> lib/.secrets.g.dart + echo "const moneroTestWalletReceiveAddress = '${{ secrets.MONERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const bitcoinTestWalletReceiveAddress = '${{ secrets.BITCOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const ethereumTestWalletReceiveAddress = '${{ secrets.ETHEREUM_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const litecoinTestWalletReceiveAddress = '${{ secrets.LITECOIN_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const bitcoinCashTestWalletReceiveAddress = '${{ secrets.BITCOIN_CASH_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const polygonTestWalletReceiveAddress = '${{ secrets.POLYGON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const solanaTestWalletReceiveAddress = '${{ secrets.SOLANA_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const tronTestWalletReceiveAddress = '${{ secrets.TRON_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const nanoTestWalletReceiveAddress = '${{ secrets.NANO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const wowneroTestWalletReceiveAddress = '${{ secrets.WOWNERO_TEST_WALLET_RECEIVE_ADDRESS }}';" >> lib/.secrets.g.dart + echo "const moneroTestWalletBlockHeight = '${{ secrets.MONERO_TEST_WALLET_BLOCK_HEIGHT }}';" >> lib/.secrets.g.dart + - name: prepare monero_c and cache run: | - echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties + export MONEROC_HASH=$(cat scripts/prepare_moneroc.sh | grep 'git checkout' | xargs | awk '{ print $3 }') + echo MONEROC_HASH=$MONEROC_HASH >> /etc/environment + mkdir -p "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c" + pushd scripts + ln -s "$MONEROC_CACHE_DIR_ROOT/moneroc-$MONEROC_HASH/monero_c" + ./prepare_moneroc.sh + popd + pushd scripts/monero_c + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" || true + mkdir -p "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" || true - - name: Build + rm -rf "$PWD/contrib/depends/built" "$PWD/monero/contrib/depends/built" "$PWD/wownero/contrib/depends/built" + rm -rf "$PWD/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources" + mkdir -p contrib/depends || true + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/built" "$PWD/contrib/depends/built" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/built" "$PWD/monero/contrib/depends/built" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/built" "$PWD/wownero/contrib/depends/built" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/contrib/depends/sources" "$PWD/contrib/depends/sources" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/monero/contrib/depends/sources" "$PWD/monero/contrib/depends/sources" + ln -sf "$MONEROC_CACHE_DIR_ROOT/_cache/wownero/contrib/depends/sources" "$PWD/wownero/contrib/depends/sources" + popd + + - name: Execute Build and Setup Commands + run: | + pushd scripts/linux + source ./app_env.sh cakewallet + ./app_config.sh + popd + + - name: Build monero_c + run: | + pushd scripts/linux/ + source ./app_env.sh cakewallet + ./build_monero_all.sh + popd + + - name: Install Flutter dependencies + run: | + flutter pub get + + - name: Build generated code + run: | + ./model_generator.sh async + + - name: Generate localization + run: | + dart run tool/generate_localization.dart + + - name: Build linux run: | - cd /opt/android/cake_wallet flutter build linux --release - - name: Prepare release zip file + - name: Compress release run: | - cd /opt/android/cake_wallet/build/linux/x64/release - zip -r ${{env.BRANCH_NAME}}.zip bundle + pushd build/linux/x64/release + zip -r cakewallet_linux.zip bundle + popd - - name: Upload Artifact + - name: Upload Artifact to github uses: kittaakos/upload-artifact-as-is@v0 with: - path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip + path: ${{ github.workspace }}/build/linux/x64/release/cakewallet_linux.zip -# Just as an artifact would be enough -# - name: Send Test APK -# continue-on-error: true -# uses: adrey/slack-file-upload-action@1.0.5 -# with: -# token: ${{ secrets.SLACK_APP_TOKEN }} -# path: /opt/android/cake_wallet/build/linux/x64/release/${{env.BRANCH_NAME}}.zip -# channel: ${{ secrets.SLACK_APK_CHANNEL }} -# title: "${{ env.BRANCH_NAME }}_linux.zip" -# filename: ${{ env.BRANCH_NAME }}_linux.zip -# initial_comment: ${{ github.event.head_commit.message }} + - name: Prepare virtual desktop + if: ${{ contains(github.event.head_commit.message, 'run tests') }} + run: | + nohup Xvfb :99 -screen 0 720x1280x16 & + echo DISPLAY=:99 | sudo tee -a $GITHUB_ENV + dbus-daemon --system --fork + nohup NetworkManager & + nohup ffmpeg -framerate 60 -video_size 720x1280 -f x11grab -i :99 -c:v libx264 -c:a aac /opt/screen_grab.mkv & + + # Note for people adding tests: + # - Tests are ran on Linux, with some things being mocked out. + # - Screen recording is being provided for the entire length of the test, you can download it in github articats. + # - Screen recordeding is encrypted, look at step "Stop screen recording, encrypt and upload", and add your key if you want + # Reason for encryption is the fact that we restore the wallet from seed, and we don't want to leak that, while there + # isn't much in those wallets anyway, we still wouldn't like to leak it to anyone who is able to access github. + + - name: Test [confirm_seeds_flow_test] + if: ${{ contains(github.event.head_commit.message, 'run tests') }} + timeout-minutes: 20 + run: | + xmessage -timeout 30 "confirm_seeds_flow_test" & + rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet + exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/confirm_seeds_flow_test.dart + - name: Test [create_wallet_flow_test] + if: ${{ contains(github.event.head_commit.message, 'run tests') }} + timeout-minutes: 20 + run: | + xmessage -timeout 30 "create_wallet_flow_test" & + rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet + exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/create_wallet_flow_test.dart + - name: Test [exchange_flow_test] + if: ${{ contains(github.event.head_commit.message, 'run tests') }} + timeout-minutes: 20 + run: | + xmessage -timeout 30 "exchange_flow_test" & + rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet + exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/exchange_flow_test.dart + - name: Test [restore_wallet_through_seeds_flow_test] + if: ${{ contains(github.event.head_commit.message, 'run tests') }} + timeout-minutes: 20 + run: | + xmessage -timeout 30 "restore_wallet_through_seeds_flow_test" & + rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet + exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart + - name: Stop screen recording, encrypt and upload + if: always() + run: | + if [[ ! -f "/opt/screen_grab.mkv" ]]; + then + exit 0; + fi + killall ffmpeg + sleep 5 + killall -9 ffmpeg || true + sleep 5 + # Feel free to add your own public key if you wish + gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 6B3199AD9B3D23B8 # konstantin@cakewallet.com + gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 35C8DBAFB8D9ACAC # cyjan@mrcyjanek.net + gpg --trust-model always --encrypt --output /opt/screen_grab.mkv.gpg \ + --recipient 6B3199AD9B3D23B8 \ + --recipient 35C8DBAFB8D9ACAC \ + /opt/screen_grab.mkv + rm /opt/screen_grab.mkv + mv /opt/screen_grab.mkv.gpg ./screen_grab.mkv.gpg + - name: Upload Artifact to github + if: always() + continue-on-error: true + uses: kittaakos/upload-artifact-as-is@v0 + with: + path: ${{ github.workspace }}/screen_grab.mkv.gpg diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index 537c9802e..2a343d430 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -9,6 +9,8 @@ import 'package:flutter/foundation.dart'; import 'package:monero/monero.dart' as monero; import 'package:mutex/mutex.dart'; +bool debugMonero = false; + int getSyncingHeight() { // final height = monero.MONERO_cw_WalletListener_height(getWlptr()); final h2 = monero.Wallet_blockChainHeight(wptr!); @@ -132,7 +134,7 @@ Future<bool> setupNodeSync( } } - if (kDebugMode) { + if (kDebugMode && debugMonero) { monero.Wallet_init3( wptr!, argv0: '', defaultLogBaseName: 'moneroc', diff --git a/integration_test/components/common_test_cases.dart b/integration_test/components/common_test_cases.dart index 83bbb0449..cc1e6d6d7 100644 --- a/integration_test/components/common_test_cases.dart +++ b/integration_test/components/common_test_cases.dart @@ -32,6 +32,11 @@ class CommonTestCases { expect(textWidget, hasWidget ? findsOneWidget : findsNothing); } + void hasTextAtLestOnce(String text, {bool hasWidget = true}) { + final textWidget = find.text(text); + expect(textWidget, hasWidget ? findsAny : findsNothing); + } + void hasType<T>() { final typeWidget = find.byType(T); expect(typeWidget, findsOneWidget); diff --git a/integration_test/components/common_test_flows.dart b/integration_test/components/common_test_flows.dart index 8350b5859..c9e605339 100644 --- a/integration_test/components/common_test_flows.dart +++ b/integration_test/components/common_test_flows.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/reactions/bip39_wallet_utils.dart'; import 'package:cake_wallet/wallet_types.g.dart'; @@ -85,6 +87,7 @@ class CommonTestFlows { await _confirmPreSeedInfo(); await _confirmWalletDetails(); + await _commonTestCases.defaultSleepTime(); } //* ========== Handles flow from welcome to restoring wallet from seeds =============== @@ -168,8 +171,8 @@ class CommonTestFlows { await _walletListPageRobot.navigateToRestoreWalletOptionsPage(); await _commonTestCases.defaultSleepTime(); - await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); - await _commonTestCases.defaultSleepTime(); + if (!Platform.isLinux) await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); + if (!Platform.isLinux) await _commonTestCases.defaultSleepTime(); await _selectWalletTypeForWallet(walletType); await _commonTestCases.defaultSleepTime(); @@ -180,6 +183,7 @@ class CommonTestFlows { //* ========== Handles setting up pin code for wallet on first install =============== Future<void> setupPinCodeForWallet(List<int> pin) async { + if (Platform.isLinux) return; // ----------- SetupPinCode Page ------------- // Confirm initial defaults - Widgets to be displayed etc await _setupPinCodeRobot.isSetupPinCodePage(); @@ -212,7 +216,7 @@ class CommonTestFlows { await _welcomePageRobot.navigateToRestoreWalletPage(); - await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); + if (!Platform.isLinux) await _restoreOptionsPageRobot.navigateToRestoreFromSeedsOrKeysPage(); await _selectWalletTypeForWallet(walletTypeToRestore); } @@ -234,6 +238,12 @@ class CommonTestFlows { await _newWalletPageRobot.generateWalletName(); + if (Platform.isLinux) { + // manual pin input + await _restoreFromSeedOrKeysPageRobot.enterPasswordForWalletRestore(CommonTestConstants.pin.join("")); + await _restoreFromSeedOrKeysPageRobot.enterPasswordRepeatForWalletRestore(CommonTestConstants.pin.join("")); + } + await _newWalletPageRobot.onNextButtonPressed(); } @@ -252,11 +262,15 @@ class CommonTestFlows { _walletSeedPageRobot.confirmWalletSeedReminderDisplays(); - await _walletSeedPageRobot.onCopySeedsButtonPressed(); + // await _walletSeedPageRobot.onCopySeedsButtonPressed(); - await _walletSeedPageRobot.onNextButtonPressed(); - - await _walletSeedPageRobot.onConfirmButtonOnSeedAlertDialogPressed(); + await _walletSeedPageRobot.onSeedPageVerifyButtonPressed(); + // Turns out the popup about "Copied to clipboard" prevents + //the button from being pressed on the first try, by just + //tapping it again we fix it. + // await _walletSeedPageRobot.onSeedPageVerifyButtonPressed(); + + await _walletSeedPageRobot.onOpenWalletButtonPressed(); } //* Main Restore Actions - On the RestoreFromSeed/Keys Page - Restore from Seeds Action @@ -277,6 +291,12 @@ class CommonTestFlows { .enterBlockHeightForWalletRestore(secrets.moneroTestWalletBlockHeight); } + if (Platform.isLinux) { + // manual pin input + await _restoreFromSeedOrKeysPageRobot.enterPasswordForWalletRestore(CommonTestConstants.pin.join("")); + await _restoreFromSeedOrKeysPageRobot.enterPasswordRepeatForWalletRestore(CommonTestConstants.pin.join("")); + } + await _restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonPressed(); } diff --git a/integration_test/funds_related_tests.dart b/integration_test/funds_related_tests.dart index db24fbc0b..27187dc2f 100644 --- a/integration_test/funds_related_tests.dart +++ b/integration_test/funds_related_tests.dart @@ -67,6 +67,11 @@ void main() { await authPageRobot.enterPinCode(CommonTestConstants.pin); } + final onAuthPageDesktop = authPageRobot.onAuthPageDesktop(); + if (onAuthPageDesktop) { + await authPageRobot.enterPassword(CommonTestConstants.pin.join("")); + } + // ----------- Exchange Confirm Page ------------- await exchangeConfirmPageRobot.isExchangeConfirmPage(); diff --git a/integration_test/robots/auth_page_robot.dart b/integration_test/robots/auth_page_robot.dart index 6358d4398..2f5c43627 100644 --- a/integration_test/robots/auth_page_robot.dart +++ b/integration_test/robots/auth_page_robot.dart @@ -20,6 +20,11 @@ class AuthPageRobot extends PinCodeWidgetRobot { return hasPin; } + bool onAuthPageDesktop() { + final hasWalletPasswordInput = find.byKey(ValueKey('enter_wallet_password')); + return hasWalletPasswordInput.tryEvaluate(); + } + Future<void> isAuthPage() async { await commonTestCases.isSpecificPage<AuthPage>(); } diff --git a/integration_test/robots/pin_code_widget_robot.dart b/integration_test/robots/pin_code_widget_robot.dart index 18dc5fba4..62e606703 100644 --- a/integration_test/robots/pin_code_widget_robot.dart +++ b/integration_test/robots/pin_code_widget_robot.dart @@ -24,6 +24,20 @@ class PinCodeWidgetRobot { commonTestCases.hasValueKey('pin_code_button_0_key'); } + Future<void> enterPassword(String password, {int pumpDuration = 100}) async { + await commonTestCases.enterText( + password, + 'enter_wallet_password', + ); + await tester.pumpAndSettle(); + await commonTestCases.tapItemByKey( + 'unlock', + ); + await tester.pumpAndSettle(); + + await commonTestCases.defaultSleepTime(); + } + Future<void> enterPinCode(List<int> pinCode, {int pumpDuration = 100}) async { for (int pin in pinCode) { await commonTestCases.tapItemByKey( diff --git a/integration_test/robots/restore_from_seed_or_key_robot.dart b/integration_test/robots/restore_from_seed_or_key_robot.dart index 9d973061b..015a9e46f 100644 --- a/integration_test/robots/restore_from_seed_or_key_robot.dart +++ b/integration_test/robots/restore_from_seed_or_key_robot.dart @@ -1,7 +1,9 @@ import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; +import 'package:cake_wallet/src/widgets/seed_widget.dart'; import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import '../components/common_test_cases.dart'; @@ -65,12 +67,28 @@ class RestoreFromSeedOrKeysPageRobot { Future<void> enterSeedPhraseForWalletRestore(String text) async { ValidatableAnnotatedEditableTextState seedTextState = - await tester.state(find.byType(ValidatableAnnotatedEditableText)); + await tester.state(find.byType(ValidatableAnnotatedEditableText)); seedTextState.widget.controller.text = text; await tester.pumpAndSettle(); } + Future<void> enterPasswordForWalletRestore(String text) async { + await commonTestCases.enterText( + text, + 'password', + ); + await tester.pumpAndSettle(); + } + + Future<void> enterPasswordRepeatForWalletRestore(String text) async { + await commonTestCases.enterText( + text, + 'repeat_wallet_password', + ); + await tester.pumpAndSettle(); + } + Future<void> enterBlockHeightForWalletRestore(String blockHeight) async { await commonTestCases.enterText( blockHeight, diff --git a/integration_test/robots/send_page_robot.dart b/integration_test/robots/send_page_robot.dart index f8e1a49ad..b705c803f 100644 --- a/integration_test/robots/send_page_robot.dart +++ b/integration_test/robots/send_page_robot.dart @@ -183,32 +183,15 @@ class SendPageRobot { } Future<void> _handleAuthPage() async { - tester.printToConsole('Inside _handleAuth'); - await tester.pump(); - tester.printToConsole('starting auth checks'); - - final authPage = authPageRobot.onAuthPage(); - - tester.printToConsole('hasAuth:$authPage'); - - if (authPage) { - await tester.pump(); - tester.printToConsole('Starting inner _handleAuth loop checks'); - - try { - await authPageRobot.enterPinCode(CommonTestConstants.pin, pumpDuration: 500); - tester.printToConsole('Auth done'); - - await tester.pump(); - - tester.printToConsole('Auth pump done'); - } catch (e) { - tester.printToConsole('Auth failed, retrying'); - await tester.pump(); - _handleAuthPage(); - } + final onAuthPage = authPageRobot.onAuthPage(); + if (onAuthPage) { + await authPageRobot.enterPinCode(CommonTestConstants.pin); + } + + final onAuthPageDesktop = authPageRobot.onAuthPageDesktop(); + if (onAuthPageDesktop) { + await authPageRobot.enterPassword(CommonTestConstants.pin.join("")); } - await tester.pump(); } Future<void> handleSendResult() async { @@ -221,7 +204,7 @@ class SendPageRobot { tester.printToConsole('Has an Error in the handle: $hasError'); - int maxRetries = 20; + int maxRetries = 3; int retries = 0; while (hasError && retries < maxRetries) { diff --git a/integration_test/robots/wallet_seed_page_robot.dart b/integration_test/robots/wallet_seed_page_robot.dart index d52f3b1ec..576bff0d6 100644 --- a/integration_test/robots/wallet_seed_page_robot.dart +++ b/integration_test/robots/wallet_seed_page_robot.dart @@ -14,8 +14,13 @@ class WalletSeedPageRobot { await commonTestCases.isSpecificPage<WalletSeedPage>(); } - Future<void> onNextButtonPressed() async { - await commonTestCases.tapItemByKey('wallet_seed_page_next_button_key'); + Future<void> onSeedPageVerifyButtonPressed() async { + await commonTestCases.tapItemByKey('wallet_seed_page_verify_seed_button_key'); + await commonTestCases.defaultSleepTime(); + } + + Future<void> onOpenWalletButtonPressed() async { + await commonTestCases.tapItemByKey('wallet_seed_page_open_wallet_button_key'); await commonTestCases.defaultSleepTime(); } @@ -38,11 +43,14 @@ class WalletSeedPageRobot { final walletSeeds = walletSeedViewModel.seed; commonTestCases.hasText(walletName); - commonTestCases.hasText(walletSeeds); + final seedList = walletSeeds.trim().split(" "); + for (final seedWord in seedList) { + commonTestCases.hasTextAtLestOnce(seedWord); + } } void confirmWalletSeedReminderDisplays() { - commonTestCases.hasText(S.current.seed_reminder); + commonTestCases.hasText(S.current.cake_seeds_save_disclaimer); } Future<void> onSaveSeedsButtonPressed() async { diff --git a/integration_test/test_suites/confirm_seeds_flow_test.dart b/integration_test/test_suites/confirm_seeds_flow_test.dart index 2d11a2cc4..a62ce3f60 100644 --- a/integration_test/test_suites/confirm_seeds_flow_test.dart +++ b/integration_test/test_suites/confirm_seeds_flow_test.dart @@ -1,9 +1,13 @@ +import 'dart:io'; + import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import '../components/common_test_cases.dart'; import '../components/common_test_constants.dart'; import '../components/common_test_flows.dart'; import '../robots/auth_page_robot.dart'; @@ -95,6 +99,10 @@ Future<void> _confirmSeedsFlowForWalletType( await authPageRobot.enterPinCode(CommonTestConstants.pin); } + final onAuthPageDesktop = authPageRobot.onAuthPageDesktop(); + if (onAuthPageDesktop) { + await authPageRobot.enterPassword(CommonTestConstants.pin.join("")); + } await tester.pumpAndSettle(); await walletKeysAndSeedPageRobot.isWalletKeysAndSeedPage(); diff --git a/integration_test/test_suites/exchange_flow_test.dart b/integration_test/test_suites/exchange_flow_test.dart index c36ef9396..8ec2e54e7 100644 --- a/integration_test/test_suites/exchange_flow_test.dart +++ b/integration_test/test_suites/exchange_flow_test.dart @@ -56,6 +56,10 @@ void main() { await authPageRobot.enterPinCode(CommonTestConstants.pin); } + final onAuthPageDesktop = authPageRobot.onAuthPageDesktop(); + if (onAuthPageDesktop) { + await authPageRobot.enterPassword(CommonTestConstants.pin.join("")); + } await exchangeConfirmPageRobot.onSavedTradeIdButtonPressed(); await exchangeTradePageRobot.onGotItButtonPressed(); }); diff --git a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart index a810aa722..0589d16ba 100644 --- a/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart +++ b/integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart @@ -1,4 +1,7 @@ +import 'dart:io'; + import 'package:cake_wallet/wallet_types.g.dart'; +import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/integration_test_runner.sh b/integration_test_runner.sh index 34c9227c0..86e28f0b8 100755 --- a/integration_test_runner.sh +++ b/integration_test_runner.sh @@ -1,4 +1,5 @@ #!/bin/bash +export DESKTOP_FORCE_MOBILE="Y" declare -a targets declare -a passed_tests @@ -12,6 +13,10 @@ done < <(find integration_test/test_suites -name "*.dart" -type f -print0) # Run each test and collect results for target in "${targets[@]}" do + if [[ "x$REMOVE_DATA_DIRECTORY" == "xY" ]]; + then + rm -rf ~/.local/share/com.example.cake_wallet ~/Documents/cake_wallet + fi echo "Running test: $target" if flutter drive \ --driver=test_driver/integration_test.dart \ diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index e63a01f61..e2d5a953c 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -221,6 +221,7 @@ class _WalletNameFormState extends State<WalletNameForm> { ), if (_walletNewVM.hasWalletPassword) ...[ TextFormField( + key: ValueKey('password'), onChanged: (value) => _walletNewVM.walletPassword = value, controller: _passwordController, textAlign: TextAlign.center, @@ -257,6 +258,7 @@ class _WalletNameFormState extends State<WalletNameForm> { ), ), TextFormField( + key: ValueKey('repeat_wallet_password'), onChanged: (value) => _walletNewVM.repeatedWalletPassword = value, controller: _repeatedPasswordController, textAlign: TextAlign.center, diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart index 83772f866..0c9af6910 100644 --- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart @@ -148,12 +148,14 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> { ), if (widget.displayWalletPassword) ...[Container( + key: ValueKey('password'), padding: EdgeInsets.only(top: 20.0), child: BaseTextFormField( controller: passwordTextEditingController, hintText: S.of(context).password, obscureText: true)), Container( + key: ValueKey('repeat_wallet_password'), padding: EdgeInsets.only(top: 20.0), child: BaseTextFormField( controller: repeatedPasswordTextEditingController, diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index 1684f6f92..6a493087b 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -223,12 +223,14 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> { ), if (widget.displayWalletPassword) ...[BaseTextFormField( + key: ValueKey('password'), controller: passwordTextEditingController, hintText: S .of(context) .password, obscureText: true), BaseTextFormField( + key: ValueKey('repeat_wallet_password'), controller: repeatedPasswordTextEditingController, hintText: S .of(context) diff --git a/lib/src/screens/wallet_unlock/wallet_unlock_page.dart b/lib/src/screens/wallet_unlock/wallet_unlock_page.dart index 3e6966f9d..4afbfe2c1 100644 --- a/lib/src/screens/wallet_unlock/wallet_unlock_page.dart +++ b/lib/src/screens/wallet_unlock/wallet_unlock_page.dart @@ -170,6 +170,7 @@ class WalletUnlockPageState extends AuthPageState<WalletUnlockPage> { SizedBox(height: 24), Form( child: TextFormField( + key: ValueKey('enter_wallet_password'), onChanged: (value) => null, controller: _passwordController, textAlign: TextAlign.center, @@ -205,6 +206,7 @@ class WalletUnlockPageState extends AuthPageState<WalletUnlockPage> { ), ), Padding( + key: ValueKey('unlock'), padding: EdgeInsets.only(bottom: 24), child: Observer( builder: (_) => LoadingPrimaryButton( diff --git a/linux/my_application.cc b/linux/my_application.cc index 49ed75499..49f9ae139 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -46,8 +46,11 @@ static void my_application_activate(GApplication* application) { } else { gtk_window_set_title(window, "Cake Wallet"); } - - gtk_window_set_default_size(window, 1280, 720); + if (getenv("DESKTOP_FORCE_MOBILE")) { + gtk_window_set_default_size(window, 720, 1280); + } else { + gtk_window_set_default_size(window, 1280, 720); + } gtk_widget_show(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); diff --git a/model_generator.sh b/model_generator.sh index 730817c24..1443b0fc9 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -1,18 +1,24 @@ #!/bin/bash set -x -e -cd cw_core; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_evm; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_monero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_bitcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_haven; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_nano; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_bitcoin_cash; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_solana; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_tron; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_wownero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .. -cd cw_polygon; flutter pub get; cd .. -cd cw_ethereum; flutter pub get; cd .. -cd cw_mweb && flutter pub get && cd .. -dart run build_runner build --delete-conflicting-outputs +for cwcoin in cw_{core,evm,monero,bitcoin,haven,nano,bitcoin_cash,solana,tron,wownero} +do + if [[ "x$1" == "xasync" ]]; + then + bash -c "cd $cwcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .." & + else + bash -c "cd $cwcoin; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd .." + fi +done +for cwcoin in cw_{polygon,ethereum,mwebd}; +do + if [[ "x$1" == "xasync" ]]; + then + bash -c "cd $cwcoin; flutter pub get; cd .." & + else + bash -c "cd $cwcoin; flutter pub get; cd .." + fi +done +flutter pub get +dart run build_runner build --delete-conflicting-outputs diff --git a/scripts/android/.gitignore b/scripts/android/.gitignore new file mode 100644 index 000000000..f7e94b7c0 --- /dev/null +++ b/scripts/android/.gitignore @@ -0,0 +1 @@ +mwebd \ No newline at end of file diff --git a/scripts/android/build_monero_all.sh b/scripts/android/build_monero_all.sh index 261ebd560..71a6b6228 100755 --- a/scripts/android/build_monero_all.sh +++ b/scripts/android/build_monero_all.sh @@ -8,50 +8,20 @@ cd "$(dirname "$0")" NPROC="-j$(nproc)" -if [[ "x$(uname)" == "xDarwin" ]]; -then - USE_DOCKER="ON" - NPROC="-j1" -fi - ../prepare_moneroc.sh -if [[ ! "x$RUNNER_OS" == "x" ]]; -then - REMOVE_CACHES=ON -fi - -# NOTE: -j1 is intentional. Otherwise you will run into weird behaviour on macos -if [[ ! "x$USE_DOCKER" == "x" ]]; -then - for COIN in monero wownero; - do - pushd ../monero_c - docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} x86_64-linux-android $NPROC" - # docker run --platform linux/amd64 -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} i686-linux-android $NPROC" - docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} armv7a-linux-androideabi $NPROC" - docker run --platform linux/amd64 -v$HOME/.cache/ccache:/root/.ccache -v$PWD:$PWD -w $PWD --rm -it git.mrcyjanek.net/mrcyjanek/debian:buster bash -c "git config --global --add safe.directory '*'; apt update; apt install -y ccache gcc g++ libtinfo5 gperf; ./build_single.sh ${COIN} aarch64-linux-android $NPROC" - popd - done -else - for COIN in monero wownero; - do - pushd ../monero_c - env -i ./build_single.sh ${COIN} x86_64-linux-android $NPROC - [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/x86_64-linux-android - # ./build_single.sh ${COIN} i686-linux-android $NPROC - # [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/i686-linux-android - env -i ./build_single.sh ${COIN} armv7a-linux-androideabi $NPROC - [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/armv7a-linux-androideabi - env -i ./build_single.sh ${COIN} aarch64-linux-android $NPROC - [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/aarch64-linux-android - - popd - unxz -f ../monero_c/release/${COIN}/x86_64-linux-android_libwallet2_api_c.so.xz - - unxz -f ../monero_c/release/${COIN}/armv7a-linux-androideabi_libwallet2_api_c.so.xz - - unxz -f ../monero_c/release/${COIN}/aarch64-linux-android_libwallet2_api_c.so.xz - [[ ! "x$REMOVE_CACHES" == "x" ]] && rm -rf ${COIN}/contrib/depends/{built,sources} - done -fi +for COIN in monero wownero; +do + pushd ../monero_c + for target in {x86_64,aarch64}-linux-android armv7a-linux-androideabi + do + if [[ -f "release/${COIN}/${target}_libwallet2_api_c.so" ]]; + then + echo "file exist, not building monero_c for ${COIN}/$target."; + else + env -i ./build_single.sh ${COIN} $target $NPROC + unxz -f ../monero_c/release/${COIN}/${target}_libwallet2_api_c.so.xz + fi + done + popd +done \ No newline at end of file diff --git a/scripts/android/build_mwebd.sh b/scripts/android/build_mwebd.sh index 4434e30f1..cd4e2c1f4 100755 --- a/scripts/android/build_mwebd.sh +++ b/scripts/android/build_mwebd.sh @@ -16,7 +16,4 @@ cd mwebd git reset --hard 555349415f76a42ec5c76152b64c4ab9aabc448f gomobile bind -target=android -androidapi 21 . mkdir -p ../../../cw_mweb/android/libs/ -mv ./mwebd.aar $_ -# cleanup: -cd .. -rm -rf mwebd \ No newline at end of file +cp ./mwebd.aar $_ \ No newline at end of file diff --git a/scripts/linux/Dockerfile.linux b/scripts/linux/Dockerfile.linux new file mode 100644 index 000000000..c8f4d3bde --- /dev/null +++ b/scripts/linux/Dockerfile.linux @@ -0,0 +1,148 @@ +# Usage: +# docker build . -f Dockerfile.linux -t ghcr.io/cake-tech/cake_wallet:main-linux +# docker push ghcr.io/cake-tech/cake_wallet:main-linux + +FROM --platform=linux/amd64 docker.io/debian:12 + +LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet + +ENV GOLANG_VERSION=1.23.4 +# comes from https://developer.android.com/studio/#command-tools +ENV ANDROID_SDK_TOOLS_VERSION=11076708 +# https://developer.android.com/studio/releases/build-tools +ENV ANDROID_PLATFORM_VERSION=34 +ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0 + +ENV FLUTTER_VERSION=3.24.0 + +# If we ever need to migrate the home directory... +RUN sed -i 's|^root:[^:]*:[^:]*:[^:]*:[^:]*:/root:|root:x:0:0:root:/root:|' /etc/passwd +# mkdir -p /root && rm -rf /root && cp -a /root /root +ENV HOME=/root +# Heavily inspired by cirrusci images +# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/tools/Dockerfile +# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34/Dockerfile +# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/34-ndk/Dockerfile +# https://github.com/cirruslabs/docker-images-flutter/blob/master/sdk/Dockerfile + +ENV ANDROID_HOME=/opt/android-sdk-linux \ + LANG=en_US.UTF-8 \ + LC_ALL=en_US.UTF-8 \ + LANGUAGE=en_US:en + +ENV ANDROID_SDK_ROOT=$ANDROID_HOME \ + PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator + +RUN set -o xtrace \ + && cd /opt \ + && apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y jq \ + && apt-get install -y default-jdk \ + && apt-get install -y sudo wget zip unzip git openssh-client curl bc software-properties-common build-essential ruby-full ruby-bundler libstdc++6 libpulse0 libglu1-mesa locales lcov libsqlite3-dev --no-install-recommends \ + # for x86 emulators + && apt-get install -y libxtst6 libnss3-dev libnspr4 libxss1 libatk-bridge2.0-0 libgtk-3-0 libgdk-pixbuf2.0-0 \ + && apt-get install -y -qq xxd \ + && apt-get install -y lftp \ + && apt-get install -qq -y sqlite3 libsqlite3-dev \ + # linux desktop dependencies + && apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev \ + # monero_c dependencies + && apt-get install -y ccache build-essential autoconf libtool gperf llvm \ + # extra stuff for KVM + && apt-get install -y udev qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils \ + # for linux tests + && apt-get install -y xvfb network-manager ffmpeg x11-utils \ + && rm -rf /var/lib/apt/lists/* \ + && sh -c 'echo "en_US.UTF-8 UTF-8" > /etc/locale.gen' \ + && locale-gen \ + && update-locale LANG=en_US.UTF-8 + +# install nodejs for actions +RUN apt-get update && \ + apt-get install -y curl && \ + curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \ + apt-get install -y nodejs && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz &&\ + rm -rf /usr/local/go &&\ + tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz + +ENV PATH=${PATH}:/usr/local/go/bin:${HOME}/go/bin +ENV GOROOT=/usr/local/go +ENV GOPATH=${HOME}/go +RUN go install golang.org/x/mobile/cmd/gomobile@latest +RUN gomobile init + +RUN wget -q https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip -O android-sdk-tools.zip \ + && mkdir -p ${ANDROID_HOME}/cmdline-tools/ \ + && unzip -q android-sdk-tools.zip -d ${ANDROID_HOME}/cmdline-tools/ \ + && mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \ + && chown -R root:root $ANDROID_HOME \ + && rm android-sdk-tools.zip \ + && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \ + && yes | sdkmanager --licenses \ + && wget -O /usr/bin/android-wait-for-emulator https://raw.githubusercontent.com/travis-ci/travis-cookbooks/master/community-cookbooks/android-sdk/files/default/android-wait-for-emulator \ + && chmod +x /usr/bin/android-wait-for-emulator \ + && sdkmanager platform-tools \ + && mkdir -p ${HOME}/.android \ + && touch ${HOME}/.android/repositories.cfg \ + && git config --global user.email "czarek@cakewallet.com" \ + && git config --global user.name "CakeWallet CI" + +# emulator is not available on linux/arm64 (https://issuetracker.google.com/issues/227219818) +RUN if [ $(uname -m) == "x86_64" ]; then sdkmanager emulator ; fi + +# Extra dependencies to not download them for cake wallet build +RUN yes | sdkmanager \ + "platforms;android-$ANDROID_PLATFORM_VERSION" \ + "build-tools;$ANDROID_BUILD_TOOLS_VERSION" \ + "platforms;android-33" \ + "build-tools;33.0.2" \ + "build-tools;33.0.1" \ + "build-tools;33.0.0" \ + "build-tools;35.0.0" + +ENV ANDROID_NDK_VERSION=27.2.12479018 + +# Extra ndk dependency for sp_scanner +RUN yes | sdkmanager "ndk;$ANDROID_NDK_VERSION" \ + "ndk;27.0.12077973" + +# https://github.com/ReactiveCircus/android-emulator-runner dependencies for tests +RUN yes | sdkmanager "system-images;android-29;default;x86" \ + "system-images;android-29;default;x86_64" \ + "system-images;android-31;default;x86_64" \ + "platforms;android-29" + +# fake the KVM status so android emulator doesn't complain (that much) +RUN (addgroup kvm || true) && \ + adduser root kvm && \ + mkdir -p /etc/udev/rules.d/ && \ + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | tee /etc/udev/rules.d/99-kvm4all.rules + +ENV PATH=${HOME}/.cargo/bin:${PATH} + +RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \ + cargo install cargo-ndk && \ + for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu; \ + do \ + rustup target add --toolchain stable $target; \ + done + + +ENV HOME=${HOME} +ENV FLUTTER_HOME=${HOME}/sdks/flutter/${FLUTTER_VERSION} +ENV FLUTTER_ROOT=$FLUTTER_HOME + +ENV PATH=${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin + +RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} + +RUN yes | flutter doctor --android-licenses \ + && flutter doctor \ + && chown -R root:root ${FLUTTER_HOME} + +RUN flutter precache diff --git a/scripts/linux/build_monero_all.sh b/scripts/linux/build_monero_all.sh index 5dc512527..558423219 100755 --- a/scripts/linux/build_monero_all.sh +++ b/scripts/linux/build_monero_all.sh @@ -1,9 +1,5 @@ #!/bin/bash - -. ./config.sh - - set -x -e cd "$(dirname "$0")" @@ -15,7 +11,15 @@ NPROC="-j$(nproc)" for COIN in monero wownero; do pushd ../monero_c - ./build_single.sh ${COIN} $(gcc -dumpmachine) $NPROC + for target in x86_64-linux-gnu + do + if [[ -f "release/${COIN}/${target}_libwallet2_api_c.so" ]]; + then + echo "file exist, not building monero_c for ${COIN}/$target."; + else + ./build_single.sh ${COIN} $target $NPROC + unxz -f ../monero_c/release/${COIN}/${target}_libwallet2_api_c.so.xz + fi + done popd - unxz -f ../monero_c/release/${COIN}/$(gcc -dumpmachine)_libwallet2_api_c.so.xz -done +done \ No newline at end of file diff --git a/scripts/prepare_moneroc.sh b/scripts/prepare_moneroc.sh index c345408dd..c0de33f6f 100755 --- a/scripts/prepare_moneroc.sh +++ b/scripts/prepare_moneroc.sh @@ -4,9 +4,9 @@ set -x -e cd "$(dirname "$0")" -if [[ ! -d "monero_c" ]]; +if [[ ! -d "monero_c/.git" ]]; then - git clone https://github.com/mrcyjanek/monero_c --branch master + git clone https://github.com/mrcyjanek/monero_c --branch master monero_c cd monero_c git checkout af5277f96073917185864d3596e82b67bee54e78 git reset --hard diff --git a/scripts/windows/.gitignore b/scripts/windows/.gitignore new file mode 100644 index 000000000..bb28076cd --- /dev/null +++ b/scripts/windows/.gitignore @@ -0,0 +1 @@ +actions-runner \ No newline at end of file diff --git a/scripts/windows/Dockerfile.windows b/scripts/windows/Dockerfile.windows new file mode 100644 index 000000000..f2a08b41c --- /dev/null +++ b/scripts/windows/Dockerfile.windows @@ -0,0 +1,68 @@ +# Usage: +# docker build . -f Dockerfile.windows -t ghcr.io/cake-tech/cake_wallet:main-windows +# docker push ghcr.io/cake-tech/cake_wallet:main-windows + +FROM mcr.microsoft.com/windows/servercore:ltsc2022 + +ENV FLUTTER_VERSION=3.24.0 +ENV GIT_VERSION=2.47.1 +ENV VS_INSTALLED_DIR="C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools" +ENV PATH="C:\Users\ContainerAdministrator\.cargo\bin;C:\ProgramData\chocolatey\bin;C:\flutter\flutter\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps" +ENV RUNNER_VERSION=2.321.0 +ENV RUNNER_URL=https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-win-x64-${RUNNER_VERSION}.zip +ENV RUNNER_WORKDIR=_work + +RUN powershell -Command \ + curl.exe -L https://aka.ms/vs/17/release/vc_redist.x64.exe -o vc_redist.x64.exe ; \ + Start-Process -Wait -FilePath .\vc_redist.x64.exe -ArgumentList '/quiet', '/install' ; \ + Remove-Item -Force vc_redist.x64.exe + +RUN powershell -Command \ + $GIT_VERSION = [Environment]::GetEnvironmentVariable('GIT_VERSION'); \ + curl.exe -L https://github.com/git-for-windows/git/releases/download/v$($GIT_VERSION).windows.1/Git-$($GIT_VERSION)-64-bit.exe -o git_installer.exe ; \ + Start-Process -Wait -FilePath .\git_installer.exe -ArgumentList '/SILENT', '/NOICONS' ; \ + Remove-Item -Force git_installer.exe + +RUN powershell -NoProfile -ExecutionPolicy Bypass -Command \ + Set-ExecutionPolicy RemoteSigned -Scope Process; \ + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; \ + Invoke-WebRequest https://chocolatey.org/install.ps1 -UseBasicP -OutFile install.ps1; \ + powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1; \ + Remove-Item -Force install.ps1 + +RUN choco install -y visualstudio2022community +RUN choco install -y visualstudio2022-workload-nativedesktop +RUN choco install -y nodejs +RUN choco install -y go +RUN choco install -y 7zip + +RUN powershell -Command \ + curl.exe -L https://win.rustup.rs -o rustup-init.exe; \ + Start-Process -Wait -FilePath .\rustup-init.exe -ArgumentList "-y"; \ + Remove-Item -Force .\rustup-init.exe + +RUN powershell -Command \ + curl.exe -L https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -o C:\Windows\System32\nuget.exe + +RUN powershell -Command \ + $FLUTTER_VERSION = [Environment]::GetEnvironmentVariable('FLUTTER_VERSION'); \ + curl.exe -L https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_$($FLUTTER_VERSION)-stable.zip -o flutter.zip ; \ + 7z x flutter.zip -oC:\flutter -bsp1 -bse1 ; \ + Remove-Item -Force flutter.zip + +RUN flutter precache + +WORKDIR C:\\actions-runner + +RUN powershell -Command \ + curl.exe -L $env:RUNNER_URL -o 'actions-runner.zip'; \ + 7z x actions-runner.zip -oC:\actions-runner -bsp1 -bse1 ; \ + Remove-Item -Path 'actions-runner.zip' + +COPY actions-runner/.credentials /actions-runner/.credentials +COPY actions-runner/.credentials_rsaparams /actions-runner/.credentials_rsaparams +COPY actions-runner/.runner /actions-runner/.runner + +COPY ci_entrypoint.ps1 /actions-runner/ci_entrypoint.ps1 + +ENTRYPOINT ["powershell", "-File", "ci_entrypoint.ps1"] \ No newline at end of file diff --git a/scripts/windows/ci_entrypoint.ps1 b/scripts/windows/ci_entrypoint.ps1 new file mode 100644 index 000000000..d68d0f5ec --- /dev/null +++ b/scripts/windows/ci_entrypoint.ps1 @@ -0,0 +1,5 @@ +$runnerDir = "C:\actions-runner" +$runCmd = "$runnerDir\run.cmd" + +Write-Host "Starting the runner..." +& $runCmd \ No newline at end of file diff --git a/scripts/windows/ci_register.ps1 b/scripts/windows/ci_register.ps1 new file mode 100644 index 000000000..a39048cdb --- /dev/null +++ b/scripts/windows/ci_register.ps1 @@ -0,0 +1,30 @@ +# Variables for paths and config +$runnerDir = "C:\actions-runner" +$configCmd = "$runnerDir\config.cmd" +$runCmd = "$runnerDir\run.cmd" + +# Check required environment variables +if (-not $env:RUNNER_TOKEN) { + Write-Error "RUNNER_TOKEN is not set. Exiting." + exit 1 +} +if (-not $env:RUNNER_REPO_URL) { + Write-Error "RUNNER_REPO_URL is not set. Exiting." + exit 1 +} +$env:RUNNER_NAME = "windows-amd64-cake" +$env:RUNNER_WORKDIR = "_work" + +# Register the runner +Write-Host "Registering the runner..." +Write-Host "--url $env:RUNNER_REPO_URL" +Write-Host "--token $env:RUNNER_TOKEN" +Write-Host "--name $env:RUNNER_NAME" +Write-Host "--work $env:RUNNER_WORKDIR" + +& $configCmd --url $env:RUNNER_REPO_URL ` + --token $env:RUNNER_TOKEN ` + --name $env:RUNNER_NAME ` + --work $env:RUNNER_WORKDIR ` + --unattended ` + --replace \ No newline at end of file From f431091f5ee5dd1d945a668c787324b9d1e9fddc Mon Sep 17 00:00:00 2001 From: cyan <cyjan@mrcyjanek.net> Date: Wed, 15 Jan 2025 14:24:29 +0100 Subject: [PATCH 9/9] Hotfix CI (#1963) * [skip slack] It looks like during our sleep github decided to break artifact upload api.. * [skip slack] Name the artifact --- .github/workflows/pr_test_build_android.yml | 5 +++-- .github/workflows/pr_test_build_linux.yml | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml index 2a7eec5c9..c5f875128 100644 --- a/.github/workflows/pr_test_build_android.yml +++ b/.github/workflows/pr_test_build_android.yml @@ -283,6 +283,7 @@ jobs: run: rm -rf build/app/outputs/flutter-apk/test-apk/ - name: Upload Artifact to github - uses: kittaakos/upload-artifact-as-is@v0 + uses: actions/upload-artifact@v4 with: - path: ${{ github.workspace }}/build/app/outputs/flutter-apk \ No newline at end of file + path: ${{ github.workspace }}/build/app/outputs/flutter-apk + name: "android apk" \ No newline at end of file diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml index 6a29e4033..345c95c4f 100644 --- a/.github/workflows/pr_test_build_linux.yml +++ b/.github/workflows/pr_test_build_linux.yml @@ -221,9 +221,10 @@ jobs: popd - name: Upload Artifact to github - uses: kittaakos/upload-artifact-as-is@v0 + uses: actions/upload-artifact@v4 with: path: ${{ github.workspace }}/build/linux/x64/release/cakewallet_linux.zip + name: cakewallet_linux - name: Prepare virtual desktop if: ${{ contains(github.event.head_commit.message, 'run tests') }} @@ -292,6 +293,7 @@ jobs: - name: Upload Artifact to github if: always() continue-on-error: true - uses: kittaakos/upload-artifact-as-is@v0 + uses: actions/upload-artifact@v4 with: path: ${{ github.workspace }}/screen_grab.mkv.gpg + name: tests_screen_grab