Compare commits

..

No commits in common. "v4.1.6" and "main" have entirely different histories.
v4.1.6 ... main

2266 changed files with 228301 additions and 30824 deletions

1
.dockerignore Normal file
View file

@ -0,0 +1 @@
*

33
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View file

@ -0,0 +1,33 @@
---
name: "Bug Report \U0001FAB2 "
about: 'Report a bug '
title: ''
labels: Bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Platform:**
- OS: [e.g. iOS 15.1, Android 14]
- Device: [e.g. iPhone 14, Galaxy S21]
- Cake Wallet Version: [e.g. 4.12.1]
**Additional context**
Add any other context about the problem here.

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Feature or Enhancement Request ✨
url: https://github.com/cake-tech/cake_wallet/discussions/new?category=feature-requests
about: Suggest an idea for Cake Wallet
- name: Not sure where to start?
url: https://docs.cakewallet.com
about: Start by reading checking out the guides!
- name: Need help?
url: https://cakewallet.com/#contact
about: Use our live chat or send a support email!

BIN
.github/assets/Logo_CakeWallet.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

48
.github/assets/NOTICE.txt vendored Normal file
View file

@ -0,0 +1,48 @@
Notice for linux-badge.svg:
1:
This is the Linux-penguin again...
Originally drewn by Larry Ewing (http://www.isc.tamu.edu/~lewing/)
(with the GIMP) the Linux Logo has been vectorized by me (Simon Budig,
http://www.home.unix-ag.org/simon/).
This happened quite some time ago with Corel Draw 4. But luckily
meanwhile there are tools available to handle vector graphics with
Linux. Bernhard Herzog (bernhard@users.sourceforge.net) deserves kudos
for creating Sketch (http://sketch.sourceforge.net), a powerful free
tool for creating vector graphics. He converted the Corel Draw file to
the Sketch native format. Since I am unable to maintain the Corel Draw
file any longer, the Sketch version now is the "official" one.
Anja Gerwinski (anja@gerwinski.de) has created an alternate version of
the penguin (penguin-variant.sk) with a thinner mouth line and slightly
altered gradients. It also features a nifty drop shadow.
The third bird (penguin-flat.sk) is a version reduced to three colors
(black/white/yellow) for e.g. silk screen printing. I made this version
for a mug, available at the friendly folks at
http://www.kernelconcepts.de/ - they do good stuff, mail Petra
(pinguin@kernelconcepts.de) if you need something special or don't
understand the german :-)
These drawings are copyrighted by Larry Ewing and Simon Budig
(penguin-variant.sk also by Anja Gerwinski), redistribution is free but
has to include this README/Copyright notice.
The use of these drawings is free. However I am happy about a sample of
your mug/t-shirt/whatever with this penguin on it...
Have fun
Simon Budig
Simon.Budig@unix-ag.org
http://www.home.unix-ag.org/simon/
Simon Budig
Am Hardtkoeppel 2
D-61279 Graevenwiesbach
2:
Attribution: lewing@isc.tamu.edu Larry Ewing and The GIMP

46
.github/assets/app-store-badge.svg vendored Executable file
View file

@ -0,0 +1,46 @@
<svg id="livetype" xmlns="http://www.w3.org/2000/svg" width="119.66407" height="40" viewBox="0 0 119.66407 40">
<title>Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917</title>
<g>
<g>
<g>
<path d="M110.13477,0H9.53468c-.3667,0-.729,0-1.09473.002-.30615.002-.60986.00781-.91895.0127A13.21476,13.21476,0,0,0,5.5171.19141a6.66509,6.66509,0,0,0-1.90088.627A6.43779,6.43779,0,0,0,1.99757,1.99707,6.25844,6.25844,0,0,0,.81935,3.61816a6.60119,6.60119,0,0,0-.625,1.90332,12.993,12.993,0,0,0-.1792,2.002C.00587,7.83008.00489,8.1377,0,8.44434V31.5586c.00489.3105.00587.6113.01515.9219a12.99232,12.99232,0,0,0,.1792,2.0019,6.58756,6.58756,0,0,0,.625,1.9043A6.20778,6.20778,0,0,0,1.99757,38.001a6.27445,6.27445,0,0,0,1.61865,1.1787,6.70082,6.70082,0,0,0,1.90088.6308,13.45514,13.45514,0,0,0,2.0039.1768c.30909.0068.6128.0107.91895.0107C8.80567,40,9.168,40,9.53468,40H110.13477c.3594,0,.7246,0,1.084-.002.3047,0,.6172-.0039.9219-.0107a13.279,13.279,0,0,0,2-.1768,6.80432,6.80432,0,0,0,1.9082-.6308,6.27742,6.27742,0,0,0,1.6172-1.1787,6.39482,6.39482,0,0,0,1.1816-1.6143,6.60413,6.60413,0,0,0,.6191-1.9043,13.50643,13.50643,0,0,0,.1856-2.0019c.0039-.3106.0039-.6114.0039-.9219.0078-.3633.0078-.7246.0078-1.0938V9.53613c0-.36621,0-.72949-.0078-1.09179,0-.30664,0-.61426-.0039-.9209a13.5071,13.5071,0,0,0-.1856-2.002,6.6177,6.6177,0,0,0-.6191-1.90332,6.46619,6.46619,0,0,0-2.7988-2.7998,6.76754,6.76754,0,0,0-1.9082-.627,13.04394,13.04394,0,0,0-2-.17676c-.3047-.00488-.6172-.01074-.9219-.01269-.3594-.002-.7246-.002-1.084-.002Z" style="fill: #a6a6a6"/>
<path d="M8.44483,39.125c-.30468,0-.602-.0039-.90429-.0107a12.68714,12.68714,0,0,1-1.86914-.1631,5.88381,5.88381,0,0,1-1.65674-.5479,5.40573,5.40573,0,0,1-1.397-1.0166,5.32082,5.32082,0,0,1-1.02051-1.3965,5.72186,5.72186,0,0,1-.543-1.6572,12.41351,12.41351,0,0,1-.1665-1.875c-.00634-.2109-.01464-.9131-.01464-.9131V8.44434S.88185,7.75293.8877,7.5498a12.37039,12.37039,0,0,1,.16553-1.87207,5.7555,5.7555,0,0,1,.54346-1.6621A5.37349,5.37349,0,0,1,2.61183,2.61768,5.56543,5.56543,0,0,1,4.01417,1.59521a5.82309,5.82309,0,0,1,1.65332-.54394A12.58589,12.58589,0,0,1,7.543.88721L8.44532.875H111.21387l.9131.0127a12.38493,12.38493,0,0,1,1.8584.16259,5.93833,5.93833,0,0,1,1.6709.54785,5.59374,5.59374,0,0,1,2.415,2.41993,5.76267,5.76267,0,0,1,.5352,1.64892,12.995,12.995,0,0,1,.1738,1.88721c.0029.2832.0029.5874.0029.89014.0079.375.0079.73193.0079,1.09179V30.4648c0,.3633,0,.7178-.0079,1.0752,0,.3252,0,.6231-.0039.9297a12.73126,12.73126,0,0,1-.1709,1.8535,5.739,5.739,0,0,1-.54,1.67,5.48029,5.48029,0,0,1-1.0156,1.3857,5.4129,5.4129,0,0,1-1.3994,1.0225,5.86168,5.86168,0,0,1-1.668.5498,12.54218,12.54218,0,0,1-1.8692.1631c-.2929.0068-.5996.0107-.8974.0107l-1.084.002Z"/>
</g>
<g id="_Group_" data-name="&lt;Group&gt;">
<g id="_Group_2" data-name="&lt;Group&gt;">
<g id="_Group_3" data-name="&lt;Group&gt;">
<path id="_Path_" data-name="&lt;Path&gt;" d="M24.76888,20.30068a4.94881,4.94881,0,0,1,2.35656-4.15206,5.06566,5.06566,0,0,0-3.99116-2.15768c-1.67924-.17626-3.30719,1.00483-4.1629,1.00483-.87227,0-2.18977-.98733-3.6085-.95814a5.31529,5.31529,0,0,0-4.47292,2.72787c-1.934,3.34842-.49141,8.26947,1.3612,10.97608.9269,1.32535,2.01018,2.8058,3.42763,2.7533,1.38706-.05753,1.9051-.88448,3.5794-.88448,1.65876,0,2.14479.88448,3.591.8511,1.48838-.02416,2.42613-1.33124,3.32051-2.66914a10.962,10.962,0,0,0,1.51842-3.09251A4.78205,4.78205,0,0,1,24.76888,20.30068Z" style="fill: #fff"/>
<path id="_Path_2" data-name="&lt;Path&gt;" d="M22.03725,12.21089a4.87248,4.87248,0,0,0,1.11452-3.49062,4.95746,4.95746,0,0,0-3.20758,1.65961,4.63634,4.63634,0,0,0-1.14371,3.36139A4.09905,4.09905,0,0,0,22.03725,12.21089Z" style="fill: #fff"/>
</g>
</g>
<g>
<path d="M42.30227,27.13965h-4.7334l-1.13672,3.35645H34.42727l4.4834-12.418h2.083l4.4834,12.418H43.438ZM38.0591,25.59082h3.752l-1.84961-5.44727h-.05176Z" style="fill: #fff"/>
<path d="M55.15969,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238H48.4302v1.50586h.03418a3.21162,3.21162,0,0,1,2.88281-1.60059C53.645,21.34766,55.15969,23.16406,55.15969,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C52.30227,29.01563,53.24953,27.81934,53.24953,25.96973Z" style="fill: #fff"/>
<path d="M65.12453,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238H58.395v1.50586h.03418A3.21162,3.21162,0,0,1,61.312,21.34766C63.60988,21.34766,65.12453,23.16406,65.12453,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C62.26711,29.01563,63.21438,27.81934,63.21438,25.96973Z" style="fill: #fff"/>
<path d="M71.71047,27.03613c.1377,1.23145,1.334,2.04,2.96875,2.04,1.56641,0,2.69336-.80859,2.69336-1.91895,0-.96387-.67969-1.541-2.28906-1.93652l-1.60937-.3877c-2.28027-.55078-3.33887-1.61719-3.33887-3.34766,0-2.14258,1.86719-3.61426,4.51855-3.61426,2.624,0,4.42285,1.47168,4.4834,3.61426h-1.876c-.1123-1.23926-1.13672-1.9873-2.63379-1.9873s-2.52148.75684-2.52148,1.8584c0,.87793.6543,1.39453,2.25488,1.79l1.36816.33594c2.54785.60254,3.60645,1.626,3.60645,3.44238,0,2.32324-1.85059,3.77832-4.79395,3.77832-2.75391,0-4.61328-1.4209-4.7334-3.667Z" style="fill: #fff"/>
<path d="M83.34621,19.2998v2.14258h1.72168v1.47168H83.34621v4.99121c0,.77539.34473,1.13672,1.10156,1.13672a5.80752,5.80752,0,0,0,.61133-.043v1.46289a5.10351,5.10351,0,0,1-1.03223.08594c-1.833,0-2.54785-.68848-2.54785-2.44434V22.91406H80.16262V21.44238H81.479V19.2998Z" style="fill: #fff"/>
<path d="M86.065,25.96973c0-2.84863,1.67773-4.63867,4.29395-4.63867,2.625,0,4.29492,1.79,4.29492,4.63867,0,2.85645-1.66113,4.63867-4.29492,4.63867C87.72609,30.6084,86.065,28.82617,86.065,25.96973Zm6.69531,0c0-1.9541-.89551-3.10742-2.40137-3.10742s-2.40039,1.16211-2.40039,3.10742c0,1.96191.89453,3.10645,2.40039,3.10645S92.76027,27.93164,92.76027,25.96973Z" style="fill: #fff"/>
<path d="M96.18606,21.44238h1.77246v1.541h.043a2.1594,2.1594,0,0,1,2.17773-1.63574,2.86616,2.86616,0,0,1,.63672.06934v1.73828a2.59794,2.59794,0,0,0-.835-.1123,1.87264,1.87264,0,0,0-1.93652,2.083v5.37012h-1.8584Z" style="fill: #fff"/>
<path d="M109.3843,27.83691c-.25,1.64355-1.85059,2.77148-3.89844,2.77148-2.63379,0-4.26855-1.76465-4.26855-4.5957,0-2.83984,1.64355-4.68164,4.19043-4.68164,2.50488,0,4.08008,1.7207,4.08008,4.46582v.63672h-6.39453v.1123a2.358,2.358,0,0,0,2.43555,2.56445,2.04834,2.04834,0,0,0,2.09082-1.27344Zm-6.28223-2.70215h4.52637a2.1773,2.1773,0,0,0-2.2207-2.29785A2.292,2.292,0,0,0,103.10207,25.13477Z" style="fill: #fff"/>
</g>
</g>
</g>
<g id="_Group_4" data-name="&lt;Group&gt;">
<g>
<path d="M37.82619,8.731a2.63964,2.63964,0,0,1,2.80762,2.96484c0,1.90625-1.03027,3.002-2.80762,3.002H35.67092V8.731Zm-1.22852,5.123h1.125a1.87588,1.87588,0,0,0,1.96777-2.146,1.881,1.881,0,0,0-1.96777-2.13379h-1.125Z" style="fill: #fff"/>
<path d="M41.68068,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C44.57522,13.99463,45.01369,13.42432,45.01369,12.44434Z" style="fill: #fff"/>
<path d="M51.57326,14.69775h-.92187l-.93066-3.31641h-.07031l-.92676,3.31641h-.91309l-1.24121-4.50293h.90137l.80664,3.436h.06641l.92578-3.436h.85254l.92578,3.436h.07031l.80273-3.436h.88867Z" style="fill: #fff"/>
<path d="M53.85354,10.19482H54.709v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915h-.88867V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
<path d="M59.09377,8.437h.88867v6.26074h-.88867Z" style="fill: #fff"/>
<path d="M61.21779,12.44434a2.13346,2.13346,0,1,1,4.24756,0,2.1338,2.1338,0,1,1-4.24756,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C64.11232,13.99463,64.5508,13.42432,64.5508,12.44434Z" style="fill: #fff"/>
<path d="M66.4009,13.42432c0-.81055.60352-1.27783,1.6748-1.34424l1.21973-.07031v-.38867c0-.47559-.31445-.74414-.92187-.74414-.49609,0-.83984.18213-.93848.50049h-.86035c.09082-.77344.81836-1.26953,1.83984-1.26953,1.12891,0,1.76563.562,1.76563,1.51318v3.07666h-.85547v-.63281h-.07031a1.515,1.515,0,0,1-1.35254.707A1.36026,1.36026,0,0,1,66.4009,13.42432Zm2.89453-.38477v-.37646l-1.09961.07031c-.62012.0415-.90137.25244-.90137.64941,0,.40527.35156.64111.835.64111A1.0615,1.0615,0,0,0,69.29543,13.03955Z" style="fill: #fff"/>
<path d="M71.34816,12.44434c0-1.42285.73145-2.32422,1.86914-2.32422a1.484,1.484,0,0,1,1.38086.79h.06641V8.437h.88867v6.26074h-.85156v-.71143h-.07031a1.56284,1.56284,0,0,1-1.41406.78564C72.0718,14.772,71.34816,13.87061,71.34816,12.44434Zm.918,0c0,.95508.4502,1.52979,1.20313,1.52979.749,0,1.21191-.583,1.21191-1.52588,0-.93848-.46777-1.52979-1.21191-1.52979C72.72121,10.91846,72.26613,11.49707,72.26613,12.44434Z" style="fill: #fff"/>
<path d="M79.23,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C82.12453,13.99463,82.563,13.42432,82.563,12.44434Z" style="fill: #fff"/>
<path d="M84.66945,10.19482h.85547v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915H87.605V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
<path d="M93.51516,9.07373v1.1416h.97559v.74854h-.97559V13.2793c0,.47168.19434.67822.63672.67822a2.96657,2.96657,0,0,0,.33887-.02051v.74023a2.9155,2.9155,0,0,1-.4834.04541c-.98828,0-1.38184-.34766-1.38184-1.21582v-2.543h-.71484v-.74854h.71484V9.07373Z" style="fill: #fff"/>
<path d="M95.70461,8.437h.88086v2.48145h.07031a1.3856,1.3856,0,0,1,1.373-.80664,1.48339,1.48339,0,0,1,1.55078,1.67871v2.90723H98.69v-2.688c0-.71924-.335-1.0835-.96289-1.0835a1.05194,1.05194,0,0,0-1.13379,1.1416v2.62988h-.88867Z" style="fill: #fff"/>
<path d="M104.76125,13.48193a1.828,1.828,0,0,1-1.95117,1.30273A2.04531,2.04531,0,0,1,100.73,12.46045a2.07685,2.07685,0,0,1,2.07617-2.35254c1.25293,0,2.00879.856,2.00879,2.27V12.688h-3.17969v.0498a1.1902,1.1902,0,0,0,1.19922,1.29,1.07934,1.07934,0,0,0,1.07129-.5459Zm-3.126-1.45117h2.27441a1.08647,1.08647,0,0,0-1.1084-1.1665A1.15162,1.15162,0,0,0,101.63527,12.03076Z" style="fill: #fff"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

BIN
.github/assets/devices.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
.github/assets/f-droid-badge.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
.github/assets/google-play-badge.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

1071
.github/assets/linux-badge.svg vendored Executable file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 67 KiB

51
.github/assets/mac-store-badge.svg vendored Executable file
View file

@ -0,0 +1,51 @@
<svg id="livetype" xmlns="http://www.w3.org/2000/svg" width="156.10054" height="40" viewBox="0 0 156.10054 40">
<title>Download_on_the_Mac_App_Store_Badge_US-UK_RGB_blk_092917</title>
<g>
<g>
<g>
<path d="M146.57123,0H9.53468c-.3667,0-.729,0-1.09473.002-.30615.002-.60986.00781-.91895.0127A13.21476,13.21476,0,0,0,5.5171.19141a6.66509,6.66509,0,0,0-1.90088.627A6.4378,6.4378,0,0,0,1.99757,1.99707,6.25844,6.25844,0,0,0,.81935,3.61816a6.60119,6.60119,0,0,0-.625,1.90332,12.993,12.993,0,0,0-.1792,2.002C.00587,7.83008.00489,8.1377,0,8.44434V31.5586c.00489.3105.00587.6113.01514.9219a12.99232,12.99232,0,0,0,.1792,2.0019,6.58756,6.58756,0,0,0,.625,1.9043A6.20778,6.20778,0,0,0,1.99757,38.001a6.27446,6.27446,0,0,0,1.61865,1.1787,6.70082,6.70082,0,0,0,1.90088.6308,13.45514,13.45514,0,0,0,2.0039.1768c.30909.0068.6128.0107.91895.0107C8.80567,40,9.168,40,9.53468,40H146.57123c.3594,0,.7246,0,1.084-.002.3047,0,.6172-.0039.9219-.0107a13.279,13.279,0,0,0,2-.1768,6.80432,6.80432,0,0,0,1.9082-.6308,6.27742,6.27742,0,0,0,1.6172-1.1787,6.39482,6.39482,0,0,0,1.1816-1.6143,6.60413,6.60413,0,0,0,.6191-1.9043,13.50643,13.50643,0,0,0,.1856-2.0019c.0039-.3106.0039-.6114.0039-.9219.0078-.3633.0078-.7246.0078-1.0938V9.53613c0-.36621,0-.72949-.0078-1.09179,0-.30664,0-.61426-.0039-.9209a13.5071,13.5071,0,0,0-.1856-2.002,6.6177,6.6177,0,0,0-.6191-1.90332,6.46619,6.46619,0,0,0-2.7988-2.7998,6.76754,6.76754,0,0,0-1.9082-.627,13.04394,13.04394,0,0,0-2-.17676c-.3047-.00488-.6172-.01074-.9219-.01269-.3594-.002-.7246-.002-1.084-.002Z" style="fill: #a6a6a6"/>
<path d="M8.44483,39.125c-.30468,0-.60205-.0039-.90429-.0107a12.68714,12.68714,0,0,1-1.86914-.1631,5.88381,5.88381,0,0,1-1.65674-.5479,5.40573,5.40573,0,0,1-1.397-1.0166,5.32082,5.32082,0,0,1-1.02051-1.3965,5.72184,5.72184,0,0,1-.543-1.6572,12.41339,12.41339,0,0,1-.1665-1.875c-.00634-.2109-.01464-.9131-.01464-.9131V8.44434S.88185,7.75293.8877,7.5498a12.37032,12.37032,0,0,1,.16553-1.87207,5.75552,5.75552,0,0,1,.54346-1.6621A5.3735,5.3735,0,0,1,2.61183,2.61768,5.56543,5.56543,0,0,1,4.01417,1.59521a5.82309,5.82309,0,0,1,1.65332-.54394A12.58589,12.58589,0,0,1,7.543.88721L8.44532.875h139.205l.9131.0127a12.38493,12.38493,0,0,1,1.8584.16259,5.93833,5.93833,0,0,1,1.6709.54785,5.59374,5.59374,0,0,1,2.415,2.41993,5.76267,5.76267,0,0,1,.5352,1.64892,12.995,12.995,0,0,1,.1738,1.88721c.0029.2832.0029.5874.0029.89014.0079.375.0079.73193.0079,1.09179V30.4648c0,.3633,0,.7178-.0079,1.0752,0,.3252,0,.6231-.0039.9297a12.73127,12.73127,0,0,1-.1709,1.8535,5.739,5.739,0,0,1-.54,1.67,5.48029,5.48029,0,0,1-1.0156,1.3857,5.4129,5.4129,0,0,1-1.3994,1.0225,5.86168,5.86168,0,0,1-1.668.5498,12.54218,12.54218,0,0,1-1.8692.1631c-.2929.0068-.5996.0107-.8974.0107l-1.084.002Z"/>
</g>
<g id="_Group_" data-name="&lt;Group&gt;">
<g id="_Group_2" data-name="&lt;Group&gt;">
<g id="_Group_3" data-name="&lt;Group&gt;">
<g id="_Group_4" data-name="&lt;Group&gt;">
<path id="_Path_" data-name="&lt;Path&gt;" d="M24.76888,20.30068a4.94881,4.94881,0,0,1,2.35656-4.15206,5.06566,5.06566,0,0,0-3.99116-2.15768c-1.67924-.17626-3.30719,1.00483-4.1629,1.00483-.87227,0-2.18977-.98733-3.6085-.95814a5.31529,5.31529,0,0,0-4.47292,2.72787c-1.934,3.34842-.49141,8.26947,1.3612,10.97608.9269,1.32535,2.01018,2.8058,3.42763,2.7533,1.38706-.05753,1.9051-.88448,3.5794-.88448,1.65876,0,2.14479.88448,3.591.8511,1.48838-.02416,2.42613-1.33124,3.32051-2.66914a10.962,10.962,0,0,0,1.51842-3.09251A4.78205,4.78205,0,0,1,24.76888,20.30068Z" style="fill: #fff"/>
<path id="_Path_2" data-name="&lt;Path&gt;" d="M22.03725,12.21089a4.87248,4.87248,0,0,0,1.11452-3.49062,4.95746,4.95746,0,0,0-3.20758,1.65961,4.63634,4.63634,0,0,0-1.14371,3.36139A4.09905,4.09905,0,0,0,22.03725,12.21089Z" style="fill: #fff"/>
</g>
</g>
<g>
<path d="M46.14895,30.49609V21.35645H46.0884l-3.74316,9.04492H40.91652l-3.75293-9.04492H37.104v9.13965H35.34816v-12.418h2.22949l4.01855,9.80176h.06836l4.01074-9.80176h2.2373v12.418Z" style="fill: #fff"/>
<path d="M49.396,27.92285c0-1.583,1.21289-2.53906,3.36523-2.668l2.47852-.1377v-.68848c0-1.00684-.66309-1.5752-1.791-1.5752a1.73035,1.73035,0,0,0-1.90137,1.27441H49.8091c.05176-1.63574,1.5752-2.79687,3.69141-2.79687,2.16016,0,3.58887,1.17871,3.58887,2.96v6.20508H55.30813V29.00684h-.043a3.23683,3.23683,0,0,1-2.85742,1.64453A2.74447,2.74447,0,0,1,49.396,27.92285Zm5.84375-.81738V26.4082l-2.22949.1377c-1.11035.06934-1.73828.55078-1.73828,1.3252,0,.792.6543,1.30859,1.65234,1.30859A2.17046,2.17046,0,0,0,55.23977,27.10547Z" style="fill: #fff"/>
<path d="M64.89309,24.55762a1.99909,1.99909,0,0,0-2.13379-1.66895c-1.42871,0-2.375,1.19629-2.375,3.08105,0,1.92773.95508,3.08887,2.3916,3.08887a1.94829,1.94829,0,0,0,2.11719-1.626h1.79A3.61835,3.61835,0,0,1,62.7593,30.6084c-2.582,0-4.26855-1.76465-4.26855-4.63867,0-2.81445,1.68652-4.63867,4.251-4.63867a3.63931,3.63931,0,0,1,3.9248,3.22656Z" style="fill: #fff"/>
<path d="M78.7593,27.13965H74.0259l-1.13672,3.35645H70.8843l4.4834-12.418h2.083l4.4834,12.418H79.895Zm-4.24316-1.54883h3.752l-1.84961-5.44727h-.05176Z" style="fill: #fff"/>
<path d="M91.61672,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438H83.0884V21.44238h1.79883v1.50586h.03418a3.21161,3.21161,0,0,1,2.88281-1.60059C90.10207,21.34766,91.61672,23.16406,91.61672,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C88.7593,29.01563,89.70656,27.81934,89.70656,25.96973Z" style="fill: #fff"/>
<path d="M101.58156,25.96973c0,2.81348-1.50586,4.62109-3.77832,4.62109a3.0693,3.0693,0,0,1-2.84863-1.584h-.043v4.48438h-1.8584V21.44238h1.79883v1.50586h.03418a3.21162,3.21162,0,0,1,2.88281-1.60059C100.06691,21.34766,101.58156,23.16406,101.58156,25.96973Zm-1.91016,0c0-1.833-.94727-3.03809-2.39258-3.03809-1.41992,0-2.375,1.23047-2.375,3.03809,0,1.82422.95508,3.0459,2.375,3.0459C98.72414,29.01563,99.67141,27.81934,99.67141,25.96973Z" style="fill: #fff"/>
<path d="M108.1675,27.03613c.1377,1.23145,1.334,2.04,2.96875,2.04,1.56641,0,2.69336-.80859,2.69336-1.91895,0-.96387-.67969-1.541-2.28906-1.93652l-1.60937-.3877c-2.28027-.55078-3.33887-1.61719-3.33887-3.34766,0-2.14258,1.86719-3.61426,4.51855-3.61426,2.624,0,4.42285,1.47168,4.4834,3.61426h-1.876c-.1123-1.23926-1.13672-1.9873-2.63379-1.9873s-2.52149.75684-2.52149,1.8584c0,.87793.65431,1.39453,2.25489,1.79l1.36816.33594c2.54785.60254,3.60645,1.626,3.60645,3.44238,0,2.32324-1.85059,3.77832-4.79395,3.77832-2.75391,0-4.61328-1.4209-4.7334-3.667Z" style="fill: #fff"/>
<path d="M119.80324,19.2998v2.14258h1.72168v1.47168h-1.72168v4.99121c0,.77539.34473,1.13672,1.10156,1.13672a5.80752,5.80752,0,0,0,.61133-.043v1.46289a5.10351,5.10351,0,0,1-1.03223.08594c-1.833,0-2.54785-.68848-2.54785-2.44434V22.91406h-1.31641V21.44238h1.31641V19.2998Z" style="fill: #fff"/>
<path d="M122.521,25.96973c0-2.84863,1.67773-4.63867,4.29395-4.63867,2.625,0,4.29492,1.79,4.29492,4.63867,0,2.85645-1.66113,4.63867-4.29492,4.63867C124.18215,30.6084,122.521,28.82617,122.521,25.96973Zm6.69531,0c0-1.9541-.89551-3.10742-2.40137-3.10742s-2.40137,1.16211-2.40137,3.10742c0,1.96191.89551,3.10645,2.40137,3.10645S129.21633,27.93164,129.21633,25.96973Z" style="fill: #fff"/>
<path d="M132.64309,21.44238h1.77246v1.541h.043a2.1594,2.1594,0,0,1,2.17773-1.63574,2.86616,2.86616,0,0,1,.63672.06934v1.73828a2.598,2.598,0,0,0-.835-.1123,1.87264,1.87264,0,0,0-1.93651,2.083v5.37012h-1.8584Z" style="fill: #fff"/>
<path d="M145.84035,27.83691c-.25,1.64355-1.85059,2.77148-3.89844,2.77148-2.63379,0-4.26855-1.76465-4.26855-4.5957,0-2.83984,1.64355-4.68164,4.19043-4.68164,2.50488,0,4.08008,1.7207,4.08008,4.46582v.63672h-6.39453v.1123a2.358,2.358,0,0,0,2.43555,2.56445,2.04834,2.04834,0,0,0,2.09082-1.27344Zm-6.28223-2.70215h4.52637a2.1773,2.1773,0,0,0-2.2207-2.29785A2.292,2.292,0,0,0,139.55813,25.13477Z" style="fill: #fff"/>
</g>
</g>
</g>
</g>
<g id="_Group_5" data-name="&lt;Group&gt;">
<g>
<path d="M37.82619,8.731a2.63964,2.63964,0,0,1,2.80762,2.96484c0,1.90625-1.03027,3.002-2.80762,3.002H35.67092V8.731Zm-1.22852,5.123h1.125a1.87588,1.87588,0,0,0,1.96777-2.146,1.881,1.881,0,0,0-1.96777-2.13379h-1.125Z" style="fill: #fff"/>
<path d="M41.68068,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C44.57521,13.99463,45.01369,13.42432,45.01369,12.44434Z" style="fill: #fff"/>
<path d="M51.57326,14.69775h-.92187l-.93066-3.31641h-.07031l-.92676,3.31641h-.91309l-1.24121-4.50293h.90137l.80664,3.436h.06641l.92578-3.436h.85254l.92578,3.436h.07031l.80273-3.436h.88867Z" style="fill: #fff"/>
<path d="M53.85354,10.19482H54.709v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915h-.88867V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
<path d="M59.09377,8.437h.88867v6.26074h-.88867Z" style="fill: #fff"/>
<path d="M61.21779,12.44434a2.13323,2.13323,0,1,1,4.24707,0,2.13358,2.13358,0,1,1-4.24707,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C64.11232,13.99463,64.5508,13.42432,64.5508,12.44434Z" style="fill: #fff"/>
<path d="M66.40041,13.42432c0-.81055.60352-1.27783,1.6748-1.34424l1.21973-.07031v-.38867c0-.47559-.31445-.74414-.92187-.74414-.49609,0-.83984.18213-.93848.50049h-.86035c.09082-.77344.81836-1.26953,1.83984-1.26953,1.12891,0,1.76563.562,1.76563,1.51318v3.07666h-.85547v-.63281h-.07031a1.515,1.515,0,0,1-1.35254.707A1.36026,1.36026,0,0,1,66.40041,13.42432Zm2.89453-.38477v-.37646l-1.09961.07031c-.62012.0415-.90137.25244-.90137.64941,0,.40527.35156.64111.835.64111A1.0615,1.0615,0,0,0,69.29494,13.03955Z" style="fill: #fff"/>
<path d="M71.34768,12.44434c0-1.42285.73145-2.32422,1.86914-2.32422a1.484,1.484,0,0,1,1.38086.79h.06641V8.437h.88867v6.26074h-.85156v-.71143h-.07031a1.56284,1.56284,0,0,1-1.41406.78564C72.07131,14.772,71.34768,13.87061,71.34768,12.44434Zm.918,0c0,.95508.4502,1.52979,1.20313,1.52979.749,0,1.21191-.583,1.21191-1.52588,0-.93848-.46777-1.52979-1.21191-1.52979C72.72072,10.91846,72.26564,11.49707,72.26564,12.44434Z" style="fill: #fff"/>
<path d="M79.22951,12.44434a2.13346,2.13346,0,1,1,4.24756,0,2.1338,2.1338,0,1,1-4.24756,0Zm3.333,0c0-.97607-.43848-1.54687-1.208-1.54687-.77246,0-1.207.5708-1.207,1.54688,0,.98389.43457,1.55029,1.207,1.55029C82.124,13.99463,82.56252,13.42432,82.56252,12.44434Z" style="fill: #fff"/>
<path d="M84.66945,10.19482h.85547v.71533h.06641a1.348,1.348,0,0,1,1.34375-.80225,1.46456,1.46456,0,0,1,1.55859,1.6748v2.915H87.605V12.00586c0-.72363-.31445-1.0835-.97168-1.0835a1.03294,1.03294,0,0,0-1.0752,1.14111v2.63428h-.88867Z" style="fill: #fff"/>
<path d="M93.51516,9.07373v1.1416h.97559v.74854h-.97559V13.2793c0,.47168.19434.67822.63672.67822a2.96657,2.96657,0,0,0,.33887-.02051v.74023a2.9155,2.9155,0,0,1-.4834.04541c-.98828,0-1.38184-.34766-1.38184-1.21582v-2.543h-.71484v-.74854h.71484V9.07373Z" style="fill: #fff"/>
<path d="M95.70461,8.437h.88086v2.48145h.07031a1.3856,1.3856,0,0,1,1.373-.80664,1.48339,1.48339,0,0,1,1.55078,1.67871v2.90723H98.69v-2.688c0-.71924-.335-1.0835-.96289-1.0835a1.05194,1.05194,0,0,0-1.13379,1.1416v2.62988h-.88867Z" style="fill: #fff"/>
<path d="M104.76125,13.48193a1.828,1.828,0,0,1-1.95117,1.30273A2.04531,2.04531,0,0,1,100.73,12.46045a2.07685,2.07685,0,0,1,2.07617-2.35254c1.25293,0,2.00879.856,2.00879,2.27V12.688h-3.17969v.0498a1.1902,1.1902,0,0,0,1.19922,1.29,1.07934,1.07934,0,0,0,1.07129-.5459Zm-3.126-1.45117h2.27441a1.08647,1.08647,0,0,0-1.1084-1.1665A1.15162,1.15162,0,0,0,101.63527,12.03076Z" style="fill: #fff"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

14
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,14 @@
Issue Number (if Applicable): Fixes #
# Description
Please include a summary of the changes and which issue is fixed / feature is added.
# Pull Request - Checklist
- [ ] Initial Manual Tests Passed
- [ ] Double check modified code and verify it with the feature/task requirements
- [ ] Format code
- [ ] Look for code duplication
- [ ] Clear naming for variables and methods
- [ ] Manual tests in accessibility mode (TalkBack on Android) passed

View file

@ -0,0 +1,305 @@
name: Automated Integration Tests
on:
# pull_request:
# branches: [main, CW-659-Transaction-History-Automated-Tests]
workflow_dispatch:
inputs:
branch:
description: "Branch name to build"
required: true
default: "main"
jobs:
Automated_integration_test:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
api-level: [29]
# arch: [x86, x86_64]
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
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.27.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: 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 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 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: Generate key properties
run: |
cd /opt/android/cake_wallet
flutter packages pub 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
flutter packages pub run tool/generate_localization.dart
- name: Build generated code
run: |
cd /opt/android/cake_wallet
./model_generator.sh
- 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
echo "const changeNowCakeWalletApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
echo "const changeNowMoneroApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart
echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart
echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart
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 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
echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const trocadorMoneroApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart
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 chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart
echo "const exolixCakeWalletApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const exolixMoneroApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
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 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
echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart
echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart
echo "const swapTradeExchangeMarkup = '${{ secrets.SWAPTRADE_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
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.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
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
# end of test secrets
echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> lib/.secrets.g.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
- name: Build
run: |
cd /opt/android/cake_wallet
flutter build apk --release --split-per-abi
# - name: Rename apk file
# run: |
# cd /opt/android/cake_wallet/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
# - name: Upload Artifact
# uses: kittaakos/upload-artifact-as-is@v0
# with:
# path: /opt/android/cake_wallet/build/app/outputs/flutter-apk/test-apk/
# - 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/app/outputs/flutter-apk/test-apk/${{env.BRANCH_NAME}}.apk
# channel: ${{ secrets.SLACK_APK_CHANNEL }}
# title: "${{ env.BRANCH_NAME }}.apk"
# filename: ${{ env.BRANCH_NAME }}.apk
# initial_comment: ${{ github.event.head_commit.message }}
- name: 🦾 Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: 🦾 Cache gradle
uses: gradle/actions/setup-gradle@v3
- name: 🦾 Cache AVD
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api-level }}
- name: 🦾 Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
force-avd-creation: false
# arch: ${{ matrix.arch }}
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
working-directory: /opt/android/cake_wallet
disable-animations: false
script: echo "Generated AVD snapshot for caching."
- name: 🚀 Integration tests on Android Emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
working-directory: /opt/android/cake_wallet
script: |
chmod a+rx integration_test_runner.sh
./integration_test_runner.sh

21
.github/workflows/no_http_imports.yaml vendored Normal file
View file

@ -0,0 +1,21 @@
name: No http imports
on: [pull_request]
jobs:
PR_test_build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Check for http package usage
if: github.event_name == 'pull_request'
run: |
GIT_GREP_OUT="$(git grep package:http | (grep .dart: || test $? = 1) | (grep -v proxy_wrapper.dart || test $? = 1) | (grep -v very_insecure_http_do_not_use || test $? = 1) || true)"
[[ "x$GIT_GREP_OUT" == "x" ]] && exit 0
echo "$GIT_GREP_OUT"
echo "There are .dart files which use http imports"
echo "Using http package breaks proxy integration"
echo "Please use ProxyWrapper.getHttpClient() from package:cw_core/utils/proxy_wrapper.dart"
exit 1

19
.github/workflows/no_print_in_dart.yaml vendored Normal file
View file

@ -0,0 +1,19 @@
name: No print statements in dart files
on: [pull_request]
jobs:
PR_test_build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Check for print() statements in dart code (use printV() instead)
if: github.event_name == 'pull_request'
run: |
GIT_GREP_OUT="$(git grep ' print(' | (grep .dart: || test $? = 1) | (grep -v print_verbose.dart || test $? = 1) | (grep -v print_verbose_dummy.dart || test $? = 1) || true)"
[[ "x$GIT_GREP_OUT" == "x" ]] && exit 0
echo "$GIT_GREP_OUT"
echo "There are .dart files which use print() statements"
echo "Please use printV from package:cw_core/utils/print_verbose.dart"
exit 1

View file

@ -0,0 +1,47 @@
name: No restricted imports in lib directory
on: [pull_request]
jobs:
check_restricted_imports:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Check for restricted imports in lib directory
if: github.event_name == 'pull_request'
run: |
RESTRICTED_PACKAGES=(
"cw_bitcoin"
"cw_bitcoin_cash"
"cw_ethereum"
"cw_evm"
"cw_haven"
"cw_mweb"
"cw_nano"
"cw_polygon"
"cw_solana"
"cw_tron"
"cw_wownero"
"cw_zano"
)
FOUND_RESTRICTED=false
for package in "${RESTRICTED_PACKAGES[@]}"; do
GREP_RESULT=$(find lib -type f -name "*.dart" -exec grep -l "import.*package:$package" {} \; || true)
if [ -n "$GREP_RESULT" ]; then
echo "Found restricted import of '$package' in the following files:"
echo "$GREP_RESULT"
FOUND_RESTRICTED=true
fi
done
if [ "$FOUND_RESTRICTED" = true ]; then
echo "Error: Restricted package imports found in lib/ directory"
echo "Please remove these imports as they are not allowed in the lib/ directory"
exit 1
else
echo "No restricted imports found. All good!"
fi

View file

@ -0,0 +1,317 @@
name: Cake Wallet Android
on: [pull_request]
defaults:
run:
shell: bash
jobs:
PR_test_build:
runs-on: linux-amd64
container:
image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly
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]
steps:
- name: Fix github actions messing up $HOME...
run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV'
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: configure git
run: |
git config --global --add safe.directory '*'
git config --global user.email "ci@cakewallet.com"
git config --global user.name "CakeWallet CI"
- name: Get the full commit message
run: |
FULL_MESSAGE="$(git log -1 --pretty=%B)"
echo "message<<EOF" >> $GITHUB_ENV
echo "$FULL_MESSAGE" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Add secrets
run: |
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
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 changeNowCakeWalletApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
echo "const changeNowMoneroApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart
echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart
echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart
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 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
echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const trocadorMoneroApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart
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 exolixCakeWalletApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const exolixMoneroApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
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 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
echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart
echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart
echo "const swapTradeExchangeMarkup = '${{ secrets.SWAPTRADE_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
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.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
# 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
# end of test secrets
echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
echo "const kryptonimApiKey = '${{ secrets.KRYPTONIM_API_KEY }}';" >> lib/.secrets.g.dart
echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> 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 Decred
run: |
set -x -e
pushd scripts/android
./build_decred.sh
popd
- name: Build generated code
run: |
flutter --version
flutter clean
rm -rf .dart_tool
rm pubspec.lock
flutter pub get
./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: |
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
echo -e "id=com.cakewallet.test_${sanitized_branch_name}\nname=${BRANCH_NAME}" > android/app.properties
- name: Build
run: |
flutter build apk --dart-define=hasDevOptions=true --release --split-per-abi
- name: Rename apk file
run: |
cd build/app/outputs/flutter-apk
mkdir test-apk
cp app-arm64-v8a-release.apk test-apk/${BRANCH_NAME}.apk
cp app-x86_64-release.apk test-apk/${BRANCH_NAME}_x86.apk
- name: Find APK file
id: find_apk
run: |
set -x
apk_file=$(ls build/app/outputs/flutter-apk/test-apk/${BRANCH_NAME}.apk || exit 1)
echo "APK_FILE=$apk_file" >> $GITHUB_ENV
- name: Upload artifact to slack
if: ${{ !contains(env.message, 'skip slack') }}
continue-on-error: true
uses: adrey/slack-file-upload-action@1.0.5
with:
token: ${{ secrets.SLACK_APP_TOKEN }}
path: ${{ env.APK_FILE }}
channel: ${{ secrets.SLACK_APK_CHANNEL }}
initial_comment: ${{ env.message }}
- name: cleanup
run: rm -rf build/app/outputs/flutter-apk/test-apk/
- name: Upload Artifact to github
uses: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/build/app/outputs/flutter-apk
name: "android apk"

View file

@ -0,0 +1,317 @@
name: Cake Wallet Linux
on: [pull_request]
defaults:
run:
shell: bash
jobs:
PR_test_build:
runs-on: linux-amd64
container:
image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly
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
steps:
- name: Fix github actions messing up $HOME...
run: 'echo HOME=/root | sudo tee -a $GITHUB_ENV'
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: configure git
run: |
git config --global --add safe.directory '*'
git config --global user.email "ci@cakewallet.com"
git config --global user.name "CakeWallet CI"
- name: Get the full commit message
run: |
FULL_MESSAGE="$(git log -1 --pretty=%B)"
echo "message<<EOF" >> $GITHUB_ENV
echo "$FULL_MESSAGE" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Add secrets
run: |
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
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 changeNowCakeWalletApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
echo "const changeNowMoneroApiKey = '${{ secrets.CHANGE_NOW_API_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreSecretKey = '${{ secrets.WYRE_SECRET_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreApiKey = '${{ secrets.WYRE_API_KEY }}';" >> lib/.secrets.g.dart
echo "const wyreAccountId = '${{ secrets.WYRE_ACCOUNT_ID }}';" >> lib/.secrets.g.dart
echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart
echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart
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 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
echo "const twitterBearerToken = '${{ secrets.TWITTER_BEARER_TOKEN }}';" >> lib/.secrets.g.dart
echo "const trocadorApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const trocadorMoneroApiKey = '${{ secrets.TROCADOR_API_KEY }}';" >> lib/.secrets.g.dart
echo "const trocadorExchangeMarkup = '${{ secrets.TROCADOR_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart
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 exolixCakeWalletApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const exolixMoneroApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart
echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart
echo "const exchangeHelperApiKey = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart
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 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
echo "const cakePayApiKey = '${{ secrets.CAKE_PAY_API_KEY }}';" >> lib/.secrets.g.dart
echo "const authorization = '${{ secrets.CAKE_PAY_AUTHORIZATION }}';" >> lib/.secrets.g.dart
echo "const CSRFToken = '${{ secrets.CSRF_TOKEN }}';" >> lib/.secrets.g.dart
echo "const swapTradeExchangeMarkup = '${{ secrets.SWAPTRADE_EXCHANGE_MARKUP }}';" >> lib/.secrets.g.dart
echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
echo "const nanoNowNodesApiKey = '${{ secrets.NANO_NOW_NODES_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
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.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
# 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
# end of test secrets
echo "const chainflipApiKey = '${{ secrets.CHAINFLIP_API_KEY }}';" >> lib/.secrets.g.dart
echo "const chainflipAffiliateFee = '${{ secrets.CHAINFLIP_AFFILIATE_FEE }}';" >> lib/.secrets.g.dart
echo "const kryptonimApiKey = '${{ secrets.KRYPTONIM_API_KEY }}';" >> lib/.secrets.g.dart
echo "const walletGroupSalt = '${{ secrets.WALLET_GROUP_SALT }}';" >> 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: 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: |
flutter build linux --dart-define=hasDevOptions=true --release
- name: Compress release
run: |
pushd build/linux/x64/release
zip -r cakewallet_linux.zip bundle
popd
- name: Upload Artifact to github
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(env.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(env.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(env.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(env.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(env.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: Test [cw_monero]
timeout-minutes: 2
run: cd cw_monero && flutter test
- 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: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/screen_grab.mkv.gpg
name: tests_screen_grab

131
.gitignore vendored
View file

@ -8,6 +8,8 @@
.buildlog/
.history
.svn/
.fvm/
.fvmrc
# IntelliJ related
*.iml
@ -85,14 +87,143 @@ cw_monero/cw_monero/android/.cxx/
**/*.g.dart
android/key.properties
android/app/key.jks
**/tool/.secrets-prod.json
**/tool/.secrets-test.json
**/tool/.secrets-config.json
**/tool/.evm-secrets-config.json
**/tool/.ethereum-secrets-config.json
**/tool/.solana-secrets-config.json
**/tool/.nano-secrets-config.json
**/tool/.tron-secrets-config.json
**/lib/.secrets.g.dart
**/cw_evm/lib/.secrets.g.dart
**/cw_solana/lib/.secrets.g.dart
**/cw_tron/lib/.secrets.g.dart
vendor/
android/app/.cxx/**
ios/Flutter/.last_build_id
/lib/generated/**
#**#
/**/#**#
**/google-services.json
**/GoogleService-Info.plist
\#*\#
.\#*
ios/build
*.sublime-workspace
*.sublime-project
shared_external/**
cw_shared_external/ios/External/
# cw_haven/**
cw_haven/ios/External/
cw_haven/android/.externalNativeBuild/
cw_haven/android/.cxx/
cw_zano/ios/External/
lib/bitcoin/bitcoin.dart
lib/monero/monero.dart
lib/haven/haven.dart
lib/ethereum/ethereum.dart
lib/bitcoin_cash/bitcoin_cash.dart
lib/nano/nano.dart
lib/polygon/polygon.dart
lib/solana/solana.dart
lib/tron/tron.dart
lib/wownero/wownero.dart
lib/zano/zano.dart
lib/decred/decred.dart
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png
ios/Runner/Info.plist
android/app/src/main/res/mipmap-*
android/app/src/main/res/drawable/ic_launcher.png
!android/app/src/main/res/drawable/launch_background.xml
!android/app/src/main/res/values/styles.xml
assets/images/app_logo.png
/pubspec.yaml
/pubspec.lock
/android/app.properties
/android/app/src/main/AndroidManifest.xml
macos/Runner/Info.plist
macos/Runner/DebugProfile.entitlements
macos/Runner/Release.entitlements
macos/Runner/Runner.entitlements
lib/core/secure_storage.dart
lib/core/secure_storage.dart
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
macos/Runner/Configs/AppInfo.xcconfig
macos/Runner.xcodeproj/project.pbxproj
integration_test/playground.dart
# Monero.dart (Monero_C)
scripts/monero_c
# iOS generated framework bin
ios/MoneroWallet.framework/MoneroWallet
ios/WowneroWallet.framework/WowneroWallet
ios/ZanoWallet.framework/ZanoWallet
*_libwallet2_api_c.dylib
.flatpak-builder
cake_wallet.flatpak
flatpak-build/
# macOS
**/Flutter/ephemeral/
**/Pods/
**/macos/Flutter/GeneratedPluginRegistrant.swift
**/macos/Flutter/ephemeral
**/xcuserdata/
# Windows
**/windows/flutter/ephemeral/
**/windows/flutter/generated_plugin_registrant.cc
**/windows/flutter/generated_plugin_registrant.h
**/windows/flutter/generated_plugins.cmake
# Linux
**/linux/flutter/ephemeral/
**/linux/flutter/generated_plugin_registrant.cc
**/linux/flutter/generated_plugin_registrant.h
**/linux/flutter/generated_plugins.cmake

View file

@ -4,7 +4,33 @@
# This file should be version controlled and should not be manually edited.
version:
revision: 20e59316b8b8474554b38493b8ca888794b0234a
channel: stable
revision: "367f9ea16bfae1ca451b9cc27c1366870b187ae2"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: windows
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: macos
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
- platform: linux
create_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
base_revision: 367f9ea16bfae1ca451b9cc27c1366870b187ae2
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

190
Dockerfile Normal file
View file

@ -0,0 +1,190 @@
# docker buildx build --push --pull --platform linux/amd64,linux/arm64 . -f Dockerfile -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly
# 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
FROM docker.io/debian:12
LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet
# Set necessary environment variables
# Set Go version to latest known-working version
ENV GOLANG_VERSION=1.24.1
# Pin Flutter version to latest known-working version
ENV FLUTTER_VERSION=3.27.0
# Pin Android Studio, platform, and build tools versions to latest known-working version
# Comes from https://developer.android.com/studio/#command-tools
ENV ANDROID_SDK_TOOLS_VERSION=13114758
# Comes from https://developer.android.com/studio/releases/build-tools
ENV ANDROID_PLATFORM_VERSION=35
ENV ANDROID_BUILD_TOOLS_VERSION=34.0.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
ENV ANDROID_HOME=/opt/android-sdk-linux \
LANG=en_US.UTF-8 \
LC_ALL=en_US.UTF-8 \
LANGUAGE=en_US:en
# Set Android SDK paths
ENV ANDROID_SDK_ROOT=$ANDROID_HOME \
PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator
# Upgrade base image
RUN apt-get update \
&& apt-get upgrade -y
# Install all build dependencies
RUN set -o xtrace \
&& cd /opt \
&& apt-get install -y --no-install-recommends --no-install-suggests \
# Core dependencies
bc build-essential curl default-jdk git jq lcov libglu1-mesa libpulse0 libsqlite3-dev libstdc++6 locales openssh-client ruby-bundler ruby-full software-properties-common sudo unzip wget zip \
# for x86 emulators
libatk-bridge2.0-0 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libnss3-dev libsqlite3-dev libxtst6 libxss1 lftp sqlite3 xxd \
# Linux desktop dependencies
clang cmake libgtk-3-dev ninja-build pkg-config \
# monero_c dependencies
autoconf automake build-essential ccache gperf libtool llvm \
# extra stuff for KVM
bridge-utils libvirt-clients libvirt-daemon-system qemu-kvm udev \
# Linux test dependencies
ffmpeg network-manager x11-utils xvfb psmisc \
# aarch64-linux-gnu dependencies
g++-aarch64-linux-gnu gcc-aarch64-linux-gnu \
# x86_64-linux-gnu dependencies
g++-x86-64-linux-gnu gcc-x86-64-linux-gnu \
# flatpak dependencies
flatpak flatpak-builder binutils elfutils patch unzip xz-utils zstd \
&& apt clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& sh -c 'echo "en_US.UTF-8 UTF-8" > /etc/locale.gen' \
&& locale-gen \
&& update-locale LANG=en_US.UTF-8
ENV FLATPAK_RUNTIME_VERSION=24.08
RUN flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo \
&& flatpak install -y flathub org.freedesktop.Platform//${FLATPAK_RUNTIME_VERSION} \
&& flatpak install -y flathub org.freedesktop.Sdk//${FLATPAK_RUNTIME_VERSION}
# Install nodejs for Github Actions
RUN curl -fsSL https://deb.nodesource.com/setup_23.x | bash - && \
apt-get install -y --no-install-recommends nodejs && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install Go
ENV PATH=${PATH}:/usr/local/go/bin:${HOME}/go/bin
ENV GOROOT=/usr/local/go
ENV GOPATH=${HOME}/go
RUN ARCH=$(uname -m) && \
if [ "$ARCH" = "x86_64" ]; then \
wget https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz -O go.tar.gz; \
elif [ "$ARCH" = "aarch64" ]; then \
wget https://go.dev/dl/go${GOLANG_VERSION}.linux-arm64.tar.gz -O go.tar.gz; \
else \
echo "Unsupported architecture: $ARCH"; exit 1; \
fi && \
rm -rf /usr/local/go && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz && \
go install golang.org/x/mobile/cmd/gomobile@latest && \
gomobile init
RUN git config --global user.email "czarek@cakewallet.com" \
&& git config --global user.name "CakeWallet CI"
# Install Android SDK commandline tools and emulator
RUN ARCH=$(uname -m) && \
if [ "$ARCH" != "x86_64" ]; then exit 0; fi \
&& 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 \
# Handle emulator not being available on linux/arm64 (https://issuetracker.google.com/issues/227219818)
RUN ARCH=$(uname -m) && \
if [ "$ARCH" != "x86_64" ]; then exit 0; fi \
&& sdkmanager emulator
# Pre-install extra Android SDK dependencies in order to not have to download them for each build
RUN ARCH=$(uname -m) && \
if [ "$ARCH" != "x86_64" ]; then exit 0; fi \
&& yes | sdkmanager \
"platforms;android-$ANDROID_PLATFORM_VERSION" \
"build-tools;$ANDROID_BUILD_TOOLS_VERSION" \
"platforms;android-33" \
"platforms;android-34" \
"platforms;android-35" \
"build-tools;33.0.2" \
"build-tools;33.0.1" \
"build-tools;33.0.0" \
"build-tools;35.0.0"
# Install extra NDK dependency for sp_scanner
ENV ANDROID_NDK_VERSION=27.2.12479018
RUN ARCH=$(uname -m) && \
if [ "$ARCH" != "x86_64" ]; then exit 0; fi \
&& yes | sdkmanager "ndk;$ANDROID_NDK_VERSION" \
"ndk;27.0.12077973"
# Install dependencies for tests
# Comes from https://github.com/ReactiveCircus/android-emulator-runner
RUN ARCH=$(uname -m) && \
if [ "$ARCH" != "x86_64" ]; then exit 0; fi \
&& yes | sdkmanager \
"system-images;android-29;default;x86_64" \
"system-images;android-31;default;x86_64" \
"platforms;android-29" \
"platforms;android-31"
# Fake the KVM status so the 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
# Install rustup, rust toolchains, and cargo-ndk
ENV PATH=${HOME}/.cargo/bin:${PATH}
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
cargo install cargo-ndk && \
for toolchain in stable nightly; \
do \
for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu; \
do \
rustup target add --toolchain $toolchain $target; \
done \
done
# Download and install Flutter
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 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} && \
cd ${FLUTTER_HOME} && \
git fetch -a
RUN yes | flutter doctor --android-licenses \
&& flutter doctor \
&& chown -R root:root ${FLUTTER_HOME}
# Download and pre-cache necessary Flutter artifacts to speed up builds
RUN flutter precache

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 Cake Technologies LLC
Copyright (c) 2018-2025 Cake Labs LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,11 +1,11 @@
Privacy Policy
Last modified: February 23, 2021
Last modified: January 24, 2024
Introduction
============
Cake Technologies Inc. ("Company" or "We") respect your privacy and are committed to protecting it through our compliance with this policy.
Cake Labs LLC ("Cake Labs", "Company", or "We") respects your privacy and are committed to protecting it through our compliance with this policy.
This policy describes the types of information we may collect from you or that you may provide when you use the App (our "App") and our practices for collecting, using, maintaining, protecting, and disclosing that information.
@ -13,70 +13,83 @@ Introduction
- On this App.
- In email, text, and other electronic messages between you and this App.
It does not apply to information collected by:
- Us offline or through any other means, including on any other App operated by Company or any third party (including our affiliates and subsidiaries)]; or
- Us offline or through any other means, including on any other App operated by the Company or any third party (including our affiliates and subsidiaries); or
- Any third party (including our affiliates and subsidiaries), including through any application or content (including advertising) that may link to or be accessible from or on the App.
Please read this policy carefully to understand our policies and practices regarding your information and how we will treat it. If you do not agree with our policies and practices, you have the choice to not use the App. By accessing or using this App, you agree to this privacy policy. This policy may change from time to time. Your continued use of this App after we make changes is deemed to be acceptance of those changes, so please check the policy periodically for updates.
Definitions
-----------
- "App" means the software program provided by the Company, downloaded by You on any electronic device, named Cake Wallet.
- "App" means any software program provided by the Company, downloaded by You on any electronic device, including but not limited to Cake Wallet and Monero.com.
- "Device" means any device that can access the App, such as a cell phone or tablet device.
- "Node" means a full Monero or Bitcoin Node, which transmits data to your App for processing and synchronization, and to which your Device transmits transactions which you would like to submit to the Monero or Bitcoin networks.
- "Cake Wallet Nodes" refers to the set of cryptocurrency nodes operated and maintained by Cake Technologies.
- "Node" means a server on a supported cryptocurrency network which transmits data to your App for processing and synchronization, and to which your Device transmits transactions which you would like to submit to the supported cryptocurrency networks. This includes full nodes, Electrum servers, and lightning network nodes.
- "Cake Labs Nodes" refers to the set of cryptocurrency nodes operated and maintained by Cake Labs LLC.
- "Service" refers to the App.
- "Third-party Service" refers to any service integrated into the Cake Wallet Application. This includes ChangeNow.
- "Usage Data" refers to data collected automatically about your usage of an Application.
- "Third-party Service" refers to any service integrated into the App. This includes but is not limited to ChangeNOW, Onramper, and MoonPay.
- "Usage Data" refers to data collected automatically about your usage of an App.
- "You" means the individual, group, corporation, or any other entity accessing or using the Service.
Information We Collect About You and How We Collect It
------------------------------------------------------
Information We Never Receive Nor Collect
----------------------------------------
Usage Data (including the date and time at which you use an application, the duration of using it, and other metadata) is NOT collected by Cake Labs through the usage of the App. Cake Labs has no reason to care about any aspect of your continued usage of our App. We believe that this data is your own property and that we have no right to collect it.
Data relating to your funds, and their security and privacy, remains on your device at ALL times. Your private keys (including your Monero private view keys), seeds, backup files, and wallet passcode are your own responsibility. This data is not received, collected, or stored by Cake Labs at any time, for any reason.
Information We May Receive But Do Not Retain
--------------------------------------------
We may receive but do NOT store information from and about users of our App, including:
- The device IP address, the block height to which your wallet is synchronized, and any transactions or channels which you use our Node to submit to supported cryptocurrency networks.
We receive this information:
- Automatically as you use the App, unless you turn certain features off in your App privacy settings.
This data is provided by connecting to the Nodes and price API maintained by Cake Labs. You have the right to choose not to provide synchronization data to Cake Labs by choosing a different Node. We provide a list of Nodes in the app that include our own and third party Nodes, or you can use your own Node (which we recommend). You have the right to choose not to connect to our Fiat API service by disabling this Fiat API in App privacy settings.
Personal Data that may be sent through the Cake Labs Nodes is limited to your device's IP address, the block height to which your wallet is synchronized, and any transactions or channels which you use our Node to submit to the supported cryptocurrency networks. Personal Data received by Cake Labs in this manner is not stored for any length of time, and thus Cake Labs is incapable of sharing this data and will not use it for any purpose beyond ensuring your appropriate connection to our Nodes.
If you decide to use a Node offered by any third party, some of which we include in our Apps, said third party will receive this Personal Data instead of Cake Labs. We take no responsibility for the actions of any third-party Node offered within the Application. We recommend connecting to your own Node to limit third party sharing of your Personal Information.
If you use our Fiat API service, you will share your IP address and the cryptocurrency and fiat currency exchange pair for which your wallet requests a spot price quote. You can disable this Fiat API in App privacy settings.
Information We May Collect About You and How We Collect It
----------------------------------------------------------
We collect several types of information from and about users of our App, including information:
- By which you may be personally identified, such as name, e-mail address, or and a/any other identifier by which you may be contacted online or offline ("personal information" or "Personal Data”), ONLY when you provide it to us;
- Device IP address, the block height to which your wallet is synchronized, and any transactions which you use our Node to submit to the Monero or Bitcoin networks.
- By which you may be personally identified, such as name, e-mail address, or and a/any other identifier by which you may be contacted online or offline ("personal information" or "Personal Data”);
- Device data and error log data;
We collect this information:
- Directly from you when you provide it to us.
- Automatically as you use the App, if you use one of the Cake Wallet Nodes. Information collected automatically may include IP address and block height.
- Directly from you ONLY when you provide it to us.
Usage Data (including the date and time at which you use an application, the duration of using it, and other metadata) is NOT collected by Cake Technologies through the usage of the App. Cake Technologies has no reason to care about any aspect of your continued usage of our App. We believe that this data is your own property and that we have no right to collect it.
Personal information is received by Cake Technologies ONLY in the event that you choose to provide it to us. This is provided either by synchronizing your wallet using the Nodes maintained by Cake Technologies, or by voluntarily contacting Cake Technologies regarding support, questions or suggestions. You also have the right to choose not to provide data to Cake Technologies, by choosing a different Node. The option to do so is provided by default with a list of Nodes, but Cake Wallet also provides the ability to add another Node not listed, or use your own Node.
Data relating to your funds, and their security and privacy, remains on your device at ALL times. Your private keys, seeds, backup files, and wallet passcode are your own responsibility. This data is not received, collected, or stored by Cake Technologies at any time, for any reason.
Personal Data collected through the Cake Wallet Nodes is limited to your device's IP address, the block height to which your wallet is synchronized, and any transactions which you use our Node to submit to the Monero or Bitcoin networks. Personal Data received by Cake Technologies in this manner is not stored for any length of time, and thus Cake Technologies is both unwilling to and incapable of sharing this data, or using it for any purpose beyond ensuring your appropriate connection to our Nodes.
If you decide to use a Node offered by any third party, some of which we offer by default in the Cake Wallet Application, said third party will receive this Personal Data instead of Cake Technologies. We take no responsibility for the actions of any third-party Node offered within the Application. If you decide to synchronize your Wallet using your own Node, neither Cake Technologies nor any third party will have access to this Personal Data.
In any of these situations, Cake Technologies takes no responsibility for interception of this data by any outside individual, group, corporation, or institution. You should understand this and take any and all appropriate actions to secure your own data.
Personal information is received by Cake Labs ONLY in the event that you choose to provide it to us by voluntarily contacting Cake Labs regarding support, questions or suggestions. You may optionally send us Error reports to help us improve the App. These Error reports contain error logs and basic device data. You can review and make modifications to these Error reports before sending them to us, or you may choose not to send them to us at all.
How We Use Your Information
---------------------------
We use information that we collect about you or that you provide to us, including any personal information:
- To present our App and its contents to you.
- To allow you to sync using the closest geographical Node: In the event that you choose to synchronize your wallet using the Node maintained by Cake Technologies, we determine your location using your IP address to redirect your Wallet to the fastest possible Node.
- To contact you: In the event that you contact Cake Technologies first, we will use the Personal Data with which you provide us, to contact you by email, Telegram, Reddit, or any other means.
- To allow you to sync using the closest geographical Node: In the event that you choose to synchronize your wallet using the Node maintained by Cake Labs, we determine your location using your IP address to redirect your Wallet to the fastest possible Node.
- To contact you: In the event that you contact Cake Labs first, we will use the Personal Data with which you provide us, to contact you by email, Telegram, Reddit, or any other means.
- To manage your requests: To attend and manage your requests to us.
- For any other purpose with your consent.
Transfer of Your Personal Data
------------------------------
Personal Data received by the Cake Wallet Nodes, or voluntarily submitted to Cake Technologies through e-mail, Telegram, Reddit, or any other method, may be transferred to computers located outside of your governmental jurisdiction, where the data protection laws may differ from yours. Your consent to this Privacy Policy, and your submission of such information, represents your agreement to this transfer.
Personal Data received by the Cake Labs Nodes, or voluntarily submitted to Cake Labs through e-mail, Telegram, Reddit, or any other method, may be transferred to computers located outside of your governmental jurisdiction, where the data protection laws may differ from yours. Your consent to this Privacy Policy, and your submission of such information, represents your agreement to this transfer.
Cake Technologies will take all necessary steps to ensure that your data is treated securely and in accordance with this Privacy Policy. No transfer of your Personal Data will take place to an organization or a country, unless there are adequate controls in place to protect the security of your data.
Cake Labs will take all necessary steps to ensure that your data is treated securely and in accordance with this Privacy Policy. No transfer of your Personal Data will take place to an organization or a country, unless there are adequate controls in place to protect the security of your data.
Disclosure of Your Information
------------------------------
We may disclose aggregated information about our users, and information that does not identify any individual, without restriction. For example, we may, from time to time, disclose the number of users who have downloaded our Application.
We may disclose personal information that we collect or you provide as described in this privacy policy:
We may disclose personal information that we collect or you provide as described in this Privacy Policy:
- To our subsidiaries and affiliates.
- To contractors, service providers, and other third parties we use to support our business and who are bound by contractual obligations to keep personal information confidential and use it only for the purposes for which we disclose it to them.
- To a buyer or other successor in the event of a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Cake Technology's assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which personal information held by Cake Technology about our App users is among the assets transferred. However, we will provide notice before this Personal Data is transferred and becomes subject to a different Privacy Policy.
- To a buyer or other successor in the event of a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Cake Labs's assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which personal information held by Cake Labs about our App users is among the assets transferred. However, we will provide notice before this Personal Data is transferred and becomes subject to a different Privacy Policy.
- To fulfill the purpose for which you provide it.
- For any other purpose disclosed by us when you provide the information.
- With your consent.
@ -84,23 +97,27 @@ Disclosure of Your Information
We may also disclose your personal information:
- To comply with any court order, law, or legal process, including to respond to any government or regulatory request.
- To enforce or apply our terms of use and other agreements, including for billing and collection purposes.
- If we believe disclosure is necessary or appropriate to protect the rights, property, or safety of Cake Technologies, our customers, or others.
- If we believe disclosure is necessary or appropriate to protect the rights, property, or safety of Cake Labs, our customers, or others.
Cake Technologies is incapable of providing any authority or government agency with data received by the Cake Wallet Nodes, because we do not store this data.
Cake Labs is incapable of providing any authority or government agency with data received by the Cake Labs Nodes, because we do not store this data.
Under certain circumstances, Cake Technologies may be required by authorities to disclose Personal Data which you voluntarily provide us, including your e-mail address, Telegram username, or Reddit username. WE STRONGLY RECOMMEND THAT YOU DO NOT TRANSMIT ANY PERSONALLY IDENTIFIABLE INFORMATION TO US VIA THESE OR ANY OTHER METHODS.
Under certain circumstances, Cake Labs may be required by authorities to disclose Personal Data which you voluntarily provide us, including your e-mail address, Telegram username, or Reddit username. WE STRONGLY RECOMMEND THAT YOU DO NOT TRANSMIT ANY PERSONALLY IDENTIFIABLE INFORMATION TO US VIA THESE OR ANY OTHER METHODS.
Data Security
-------------
You are responsible for your personal data, including all data related to the safety of your funds. You should take all appropriate action to protect this data. Cake Technologies cannot recover any data related to your funds in the event that you lose or give away this data. Cake Technologies strongly recommends that you take action to secure your funds, by writing down your seeds or keys, storing encrypted backups, and never sharing this information.
You are responsible for your personal data, including all data related to the safety of your funds. You should take all appropriate action to protect this data. Cake Labs cannot recover any data related to your funds in the event that you lose or give away this data. Cake Labs strongly recommends that you take action to secure your funds, by writing down your seeds or keys, storing encrypted backups, and never sharing this information.
Cake Technologies undertakes any and all reasonable steps possible to secure any data that you voluntarily transmit to us. However, we cannot guarantee that any outside system used to transmit this data is entirely secure and, as such, we recommend that you exercise caution when voluntarily transmitting data to us.
Cake Labs undertakes any and all reasonable steps possible to secure any data that you voluntarily transmit to us. However, we cannot guarantee that any outside system used to transmit this data is entirely secure and, as such, we recommend that you exercise caution when voluntarily transmitting data to us.
In any situation, Cake Labs takes no responsibility for interception of personal data by any outside individual, group, corporation, or institution. You should understand this and take any and all appropriate actions to secure your own data.
Links to Other Websites
-----------------------
Other Websites and Third-Party Services
---------------------------------------
The App may contain links to other websites that are not operated by us. If you click on a third-party link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit. We have no control over and assume no responsibility for the content, privacy policies or practices of any third-party sites or services.
The App may contain links to other websites that are not operated by us. If you click on a Third-Party Service link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit. We have no control over and assume no responsibility for the content, privacy policies or practices of any third-party sites or services.
The App includes several optional Third-Party Services, which may not be available to all users. If you use Third-Party Services, you must agree to their respective Privacy Policies. When using certain optional features in the app such as buying and selling, you may be asked to provide information to a Third-Party Service. You will need to read and accept the privacy policy for that third party. This Third-Party Service may ask for your name, your photo ID, your social security number or other similar number, mailing address, cryptocurrency address, or other information. They may ask you to take a selfie image. Information shared with a Third-Party Service is subject to their respective Privacy Policies.
Changes to Our Privacy Policy
-----------------------------
@ -110,4 +127,4 @@ Changes to Our Privacy Policy
Contact Us
----------
If you have any questions about this Privacy Policy, you are encouraged to contact us by email at info@cakewallet.com.
If you have any questions about this Privacy Policy, you are encouraged to contact us by email at info@cakewallet.com.

188
README.md
View file

@ -1,8 +1,190 @@
# CakeWallet for Android and iOS
<div align="center">
## Open Source Monero and Bitcoin Wallet
![logo](.github/assets/Logo_CakeWallet.png)
</div>
![devices](.github/assets/devices.png)
<div align="center">
[<img height="42" src=".github/assets/app-store-badge.svg">](https://apps.apple.com/us/app/cake-wallet/id1334702542?platform=iphone)
[<img height="42" src=".github/assets/google-play-badge.png">](https://play.google.com/store/apps/details?id=com.cakewallet.cake_wallet)
[<img height="42" src=".github/assets/f-droid-badge.png">](https://fdroid.cakelabs.com)
[<img height="42" src=".github/assets/mac-store-badge.svg">](https://apps.apple.com/us/app/cake-wallet/id1334702542?platform=mac)
[<img height="42" src=".github/assets/linux-badge.svg">](https://github.com/cake-tech/cake_wallet/releases)
</div>
# Cake Wallet
[Cake Wallet](https://cakewallet.com) is an open-source, non-custodial, and private multi-currency crypto wallet for Android, iOS, macOS, and Linux.
Cake Wallet includes support for several cryptocurrencies, including:
* Monero (XMR)
* Bitcoin (BTC)
* Ethereum (ETH)
* Litecoin (LTC)
* Bitcoin Cash (BCH)
* Polygon (POL)
* Solana (SOL)
* Tron (TRX)
* Nano (XNO)
* Zano (ZANO)
* Decred (DCR)
* Wownero (WOW)
## Features
### App-Wide Features
* Completely noncustodial. *Your keys, your coins.*
* Built-in exchange for dozens of pairs
* Easily pay cryptocurrency invoices with fixed rate exchanges
* Buy cryptocurrency (BTC/LTC/XMR/ETH) with credit/debit/bank
* Sell cryptocurrency by bank transfer
* Scan QR codes for easy cryptocurrency transfers
* Create several wallets
* Select your own custom nodes/servers
* Address book
* Backup to an external location or iCloud
* Send to OpenAlias, Unstoppable Domains, Yats, and FIO Crypto Handles
* Set desired network fee level
* Store local transaction notes
* Extremely simple user experience
* Convenient exchange and sending templates for recurring payments
* Create donation links and invoices in the receive screen
* Robust privacy settings (eg: Tor-only connections)
* Robust security settings (eg: Cake 2FA)
### Monero Specific Features
* The Monero view key is retained on the device for maximum privacy
* Full support for Monero subaddresses and accounts
* Specify restore height for faster syncing
* Specify multiple recipients for batch sending
* Optionally set Monero nodes as trusted for faster syncing
* Specify a proxy for Monero nodes, compatible with Tor and i2p
### Bitcoin Specific Features
* Bitcoin coin control (specify specific outputs to spend)
* Automatically generate new addresses
* Specify multiple recipients for batch sending
### Ethereum Specific Features
* Store ETH and all ERc-20 tokens
* Add custom tokens by contract address
* Enable or disable Etherscan for transaction history
### Litecoin Specific Features
* Litecoin coin control (specify specific outputs to spend)
* Automatically generate new addresses
* Specify multiple recipients for batch sending
# Monero.com by Cake Wallet for Android and iOS
## Open Source Monero-Only Wallet
*Exchanging to/from other assets is also supported.*
## Links
* Website: https://monero.com
* App Store (iOS): https://apps.apple.com/app/id1601990386
* Google Play: https://play.google.com/store/apps/details?id=com.monero.app
* F-Droid: https://fdroid.cakelabs.com
* APK: https://github.com/cake-tech/cake_wallet/releases
### APK Verification
APK releases on GitHub, Accrescent, and F-Droid use the same key. They can easily be verified using [apksigner](https://developer.android.com/tools/apksigner#options-verify) or [AppVerifier](https://github.com/soupslurpr/AppVerifier).
See below for Cake Wallet's SHA-256 signing certificate hash:
```
com.cakewallet.cake_wallet
C5:40:53:AB:0F:10:D9:54:17:62:A3:DA:76:65:AE:3D:BA:5E:7C:74:3A:B4:F1:08:A5:34:9D:62:AC:10:6E:F5
```
# Support
We have 24/7 free support. Please contact support@cakewallet.com
We have excellent user guides, which are also open-source and open for contributions: https://guides.cakewallet.com
# Build Instructions
More instructions to follow
For instructions on how to build for Android: please view file `howto-build-android.md`
For instructions on how to build for Android: please view file `howto-build-android.md`
# Contributing
## Improving translations
Edit the applicable `strings_XX.arb` file in `res/values/` and open a pull request with the changes.
## Current list of language files:
- English
- Spanish
- French
- German
- Italian
- Portuguese
- Dutch
- Polish
- Croatian
- Russian
- Ukrainian
- Hindi
- Japanese
- Chinese
- Korean
- Thai
- Arabic
- Turkish
- Burmese
- Urdu
- Bulgarian
- Czech
- Indonesian
- Hausa
- Yoruba
## Add a new language
1. Create a new `strings_XX.arb` file in `res/values/`, replacing XX with the language's [ISO 639-1 code](https://en.wikipedia.org/wiki/ISO_639-1).
2. Edit the strings in this file, replacing XXX below with the translation for each string.
`"welcome": "Welcome to",` -> `"welcome": "XXX",`
3. For strings where there is a variable, denoted by a $ symbol and braces, such as ${status}, the string in braces should not be translated. For example, when editing line 106:
"time" : "${minutes}m ${seconds}s"
The only parts to be translated, if needed, are the values m and s after the variables.
4. Add the language to `lib/entities/language_service.dart` under both `supportedLocales` and `localeCountryCode`. Use the name of the language in the local language and in English in parentheses after for `supportedLocales`. Use the [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) for `localeCountryCode`. You must choose one country, so choose the country with the most native speakers of this language or is otherwise best associated with this language.
5. Add a relevant flag to `assets/images/flags/XXXX.png`, replacing XXXX with the 3 letters localeCountryCode. The image must be 42x26 pixels with 3 pixels of transparent margin on all 4 sides. You can resize the flag with [paint.net](https://www.getpaint.net/) to 36x20 pixels, expand the canvas to 42x26 pixels with the flag anchored in the middle, and then manually delete the 3 pixels on each side to make it transparent. Or you can use another program like Photoshop.
6. Add the new language code to `tool/utils/translation/translation_constants.dart`
## Add a new fiat currency
1. Check with [Cake Wallet support](https://guides.cakewallet.com) to see if the desired new fiat currency is available through our fiat API. Not all fiat currencies are.
2. If the currency is associated strongly with a specific issuing country, map the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code with the applicable [ISO 3166-1 alpha-3 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) in `lib/entities/fiat_currency.dart`. If the currency is used in a whole region or organization, then map with a reasonable interpretation of this (eg: eur countryCode for EUR symbol).
3. Add the raw mapping underneath in `lib/entities/fiat_currency.dart` following the same format as the others.
4. Add a flag of the issuing country or organization to `assets/images/flags/XXXX.png`, replacing XXXX with the ISO 3166-1 alpha-3 code used above (eg: `usa.png`, `eur.png`). Do not add this if the flag with the same name already exists. The image must be 42x26 pixels with a 3 pixels of transparent margin on all 4 sides.
---
Copyright (C) 2018-2023 Cake Labs LLC

View file

@ -1,55 +1,88 @@
include: package:lints/recommended.yaml
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
exclude:
- "build/**"
- "lib/generated/*.dart"
- "**.g.dart"
exclude: [
build/**,
lib/**.g.dart,
cw_core/lib/**.g.dart,
cw_haven/lib/**.g.dart,
cw_monero/lib/**.g.dart,
lib/generated/*.dart,
cw_monero/ios/External/**,
cw_shared_external/**,
shared_external/**,
lib/bitcoin/cw_bitcoin.dart,
lib/bitcoin_cash/cw_bitcoin_cash.dart,
lib/ethereum/cw_ethereum.dart,
lib/haven/cw_haven.dart,
lib/monero/cw_monero.dart,
lib/nano/cw_nano.dart,
lib/polygon/cw_polygon.dart,
lib/solana/cw_solana.dart,
lib/tron/cw_tron.dart,
lib/wownero/cw_wownero.dart,
lib/zano/cw_zano.dart,
]
language:
strict-casts: true
strict-raw-types: true
linter:
rules:
- always_declare_return_types
- annotate_overrides
- avoid_empty_else
- avoid_init_to_null
- avoid_return_types_on_setters
- await_only_futures
- camel_case_types
- cancel_subscriptions
- close_sinks
- comment_references
- constant_identifier_names
- control_flow_in_finally
- empty_catches
- empty_constructor_bodies
- empty_statements
- hash_and_equals
- implementation_imports
- invariant_booleans
- iterable_contains_unrelated_type
- library_names
- library_prefixes
- list_remove_unrelated_type
- literal_only_boolean_expressions
- non_constant_identifier_names
- one_member_abstracts
- only_throw_errors
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
- parameter_assignments
- always_declare_return_types
- prefer_final_fields
- prefer_final_locals
- prefer_is_not_empty
- slash_for_doc_comments
- sort_constructors_first
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- type_init_formals
- unawaited_futures
- unnecessary_getters_setters
- unrelated_type_equality_checks
- valid_regexps
# analyzer:
# strong-mode:
# implicit-casts: false
# implicit-dynamic: false
# exclude: [build/**, lib/generated/*.dart, lib/**.g.dart, cw_monero/ios/External/**, cw_shared_external/**, shared_external/**]
# linter:
# rules:
# - always_declare_return_types
# - annotate_overrides
# - avoid_empty_else
# - avoid_init_to_null
# - avoid_return_types_on_setters
# - await_only_futures
# - camel_case_types
# - cancel_subscriptions
# - close_sinks
# - comment_references
# - constant_identifier_names
# - control_flow_in_finally
# - empty_catches
# - empty_constructor_bodies
# - empty_statements
# - hash_and_equals
# - invariant_booleans
# - iterable_contains_unrelated_type
# - library_names
# - library_prefixes
# - list_remove_unrelated_type
# - literal_only_boolean_expressions
# - non_constant_identifier_names
# - one_member_abstracts
# - only_throw_errors
# - overridden_fields
# - package_api_docs
# - package_names
# - package_prefixed_library_names
# - parameter_assignments
# - prefer_final_fields
# - prefer_final_locals
# - prefer_is_not_empty
# - slash_for_doc_comments
# - sort_constructors_first
# - sort_unnamed_constructors_first
# - test_types_in_equals
# - throw_in_finally
# - type_init_formals
# - unawaited_futures
# - unnecessary_getters_setters
# - unrelated_type_equality_checks
# - valid_regexps

View file

@ -1,2 +1,2 @@
connection.project.dir=
eclipse.preferences.version=1
eclipse.preferences.version=1

View file

@ -1,3 +1,9 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
@ -21,30 +22,44 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
def appProperties = new Properties()
def appPropertiesFile = rootProject.file('app.properties')
if (appPropertiesFile.exists()) {
appProperties.load(new FileInputStream(appPropertiesFile))
}
android {
compileSdkVersion 29
compileSdkVersion 35
buildToolsVersion "35.0.0"
lintOptions {
disable 'InvalidPackage'
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
namespace "com.cakewallet.cake_wallet"
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.cakewallet.cake_wallet"
minSdkVersion 21
targetSdkVersion 29
applicationId appProperties['id']
minSdkVersion 24
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [APP_NAME: appProperties['name']]
externalNativeBuild {
cmake {
@ -66,13 +81,14 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.release
}
}
ndkVersion "27.0.12077973"
}
flutter {
@ -81,6 +97,12 @@ flutter {
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}
configurations {
implementation.exclude module:'proto-google-common-protos'
implementation.exclude module:'protolite-well-known-types'
implementation.exclude module:'protobuf-javalite'
}

View file

@ -5,4 +5,98 @@
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-dontwarn io.flutter.embedding.**
-dontwarn io.flutter.embedding.**
-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
# start reown
-dontwarn com.github.luben.zstd.BufferPool
-dontwarn com.github.luben.zstd.ZstdInputStream
-dontwarn com.github.luben.zstd.ZstdOutputStream
-dontwarn com.google.api.client.http.GenericUrl
-dontwarn com.google.api.client.http.HttpHeaders
-dontwarn com.google.api.client.http.HttpRequest
-dontwarn com.google.api.client.http.HttpRequestFactory
-dontwarn com.google.api.client.http.HttpResponse
-dontwarn com.google.api.client.http.HttpTransport
-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder
-dontwarn com.google.api.client.http.javanet.NetHttpTransport
-dontwarn java.awt.Color
-dontwarn java.awt.Dimension
-dontwarn java.awt.Graphics2D
-dontwarn java.awt.Graphics
-dontwarn java.awt.Image
-dontwarn java.awt.Point
-dontwarn java.awt.Polygon
-dontwarn java.awt.Shape
-dontwarn java.awt.color.ColorSpace
-dontwarn java.awt.geom.AffineTransform
-dontwarn java.awt.image.BufferedImage
-dontwarn java.awt.image.ColorModel
-dontwarn java.awt.image.ComponentColorModel
-dontwarn java.awt.image.ComponentSampleModel
-dontwarn java.awt.image.DataBuffer
-dontwarn java.awt.image.DataBufferByte
-dontwarn java.awt.image.DataBufferInt
-dontwarn java.awt.image.DataBufferUShort
-dontwarn java.awt.image.ImageObserver
-dontwarn java.awt.image.MultiPixelPackedSampleModel
-dontwarn java.awt.image.Raster
-dontwarn java.awt.image.RenderedImage
-dontwarn java.awt.image.SampleModel
-dontwarn java.awt.image.SinglePixelPackedSampleModel
-dontwarn java.awt.image.WritableRaster
-dontwarn java.beans.BeanInfo
-dontwarn java.beans.FeatureDescriptor
-dontwarn java.beans.IntrospectionException
-dontwarn java.beans.Introspector
-dontwarn java.beans.PropertyDescriptor
-dontwarn java.lang.reflect.InaccessibleObjectException
-dontwarn javax.imageio.IIOImage
-dontwarn javax.imageio.ImageIO
-dontwarn javax.imageio.ImageWriteParam
-dontwarn javax.imageio.ImageWriter
-dontwarn javax.imageio.metadata.IIOMetadata
-dontwarn javax.imageio.stream.ImageOutputStream
-dontwarn javax.swing.JComponent
-dontwarn javax.swing.JFileChooser
-dontwarn javax.swing.JFrame
-dontwarn javax.swing.JPanel
-dontwarn javax.swing.ProgressMonitor
-dontwarn javax.swing.SwingUtilities
-dontwarn org.brotli.dec.BrotliInputStream
-dontwarn org.joda.time.Instant
-dontwarn org.objectweb.asm.AnnotationVisitor
-dontwarn org.objectweb.asm.Attribute
-dontwarn org.objectweb.asm.ClassReader
-dontwarn org.objectweb.asm.ClassVisitor
-dontwarn org.objectweb.asm.FieldVisitor
-dontwarn org.objectweb.asm.Label
-dontwarn org.objectweb.asm.MethodVisitor
-dontwarn org.objectweb.asm.Type
-dontwarn org.tukaani.xz.ARMOptions
-dontwarn org.tukaani.xz.ARMThumbOptions
-dontwarn org.tukaani.xz.DeltaOptions
-dontwarn org.tukaani.xz.FilterOptions
-dontwarn org.tukaani.xz.FinishableOutputStream
-dontwarn org.tukaani.xz.FinishableWrapperOutputStream
-dontwarn org.tukaani.xz.IA64Options
-dontwarn org.tukaani.xz.LZMA2InputStream
-dontwarn org.tukaani.xz.LZMA2Options
-dontwarn org.tukaani.xz.LZMAInputStream
-dontwarn org.tukaani.xz.LZMAOutputStream
-dontwarn org.tukaani.xz.MemoryLimitException
-dontwarn org.tukaani.xz.PowerPCOptions
-dontwarn org.tukaani.xz.SPARCOptions
-dontwarn org.tukaani.xz.SingleXZInputStream
-dontwarn org.tukaani.xz.UnsupportedOptionsException
-dontwarn org.tukaani.xz.X86Options
-dontwarn org.tukaani.xz.XZ
-dontwarn org.tukaani.xz.XZInputStream
-dontwarn org.tukaani.xz.XZOutputStream
-dontwarn us.hebi.matlab.mat.ejml.Mat5Ejml
-dontwarn us.hebi.matlab.mat.format.Mat5
-dontwarn us.hebi.matlab.mat.format.Mat5File
-dontwarn us.hebi.matlab.mat.types.Array
-dontwarn us.hebi.matlab.mat.types.MatFile$Entry
-dontwarn us.hebi.matlab.mat.types.MatFile
# end reown

View file

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cakewallet.cake_wallet">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

View file

@ -1,37 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cakewallet.cake_wallet">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<application
android:label="Cake Wallet"
android:allowBackup="false"
android:fullBackupContent="false"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait">
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

View file

@ -0,0 +1,140 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- bibo01 : hardware option-->
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
<!-- required for API 18 - 30 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
<!-- required for API <= 29 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<!-- API 31+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<application
android:name=".Application"
android:label="${APP_NAME}"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:fullBackupContent="false"
android:versionCode="__versionCode__"
android:versionName="__versionName__"
android:requestLegacyExternalStorage="true"
android:extractNativeLibs="true">
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
android:exported="false" />
<activity
android:name=".MainActivity"
android:launchMode="singleInstance"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="cakewallet"
android:host="y.at" />
</intent-filter>
<!-- currencies qr code scheme -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="__APP_SCHEME__" />
<data android:scheme="bitcoin" />
<data android:scheme="bitcoin-wallet" />
<data android:scheme="bitcoin_wallet" />
<data android:scheme="monero" />
<data android:scheme="monero-wallet" />
<data android:scheme="monero_wallet" />
<data android:scheme="litecoin" />
<data android:scheme="litecoin-wallet" />
<data android:scheme="litecoin_wallet" />
<data android:scheme="ethereum" />
<data android:scheme="ethereum-wallet" />
<data android:scheme="ethereum_wallet" />
<data android:scheme="nano" />
<data android:scheme="nano-wallet" />
<data android:scheme="nano_wallet" />
<data android:scheme="bitcoincash" />
<data android:scheme="bitcoincash-wallet" />
<data android:scheme="bitcoincash_wallet" />
<data android:scheme="polygon" />
<data android:scheme="polygon-wallet" />
<data android:scheme="polygon_wallet" />
<data android:scheme="solana-wallet" />
<data android:scheme="tron" />
<data android:scheme="tron-wallet" />
<data android:scheme="tron_wallet" />
<data android:scheme="wownero" />
<data android:scheme="wownero-wallet" />
<data android:scheme="wownero_wallet" />
<data android:scheme="zano" />
<data android:scheme="zano-wallet" />
<data android:scheme="zano_wallet" />
<data android:scheme="decred" />
<data android:scheme="decred-wallet" />
<data android:scheme="decred_wallet" />
</intent-filter>
<!-- nano-gpt link scheme -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nano-gpt" />
</intent-filter>
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
<provider
android:name="com.pichillilorenzo.flutter_inappwebview_android.InAppWebViewFileProvider"
android:authorities="${applicationId}.flutter_inappwebview_android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
</manifest>

View file

@ -0,0 +1,11 @@
package com.cakewallet.cake_wallet;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class Application extends FlutterApplication implements PluginRegistrantCallback {
@Override
public void registerWith(PluginRegistry registry) {}
}

View file

@ -1,15 +1,93 @@
package com.cakewallet.cake_wallet;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;
import android.content.Intent;
import android.net.Uri;
import android.os.PowerManager;
import android.provider.Settings;
import java.security.SecureRandom;
public class MainActivity extends FlutterFragmentActivity {
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
boolean isAppSecure = false;
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel utilsChannel =
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
UTILS_CHANNEL);
utilsChannel.setMethodCallHandler(this::handle);
}
}
private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
Handler handler = new Handler(Looper.getMainLooper());
try {
switch (call.method) {
case "sec_random":
int count = call.argument("count");
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[count];
random.nextBytes(bytes);
handler.post(() -> result.success(bytes));
break;
case "setIsAppSecure":
isAppSecure = call.argument("isAppSecure");
if (isAppSecure) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
break;
case "disableBatteryOptimization":
disableBatteryOptimization();
handler.post(() -> result.success(null));
break;
case "isBatteryOptimizationDisabled":
boolean isDisabled = isBatteryOptimizationDisabled();
handler.post(() -> result.success(isDisabled));
break;
default:
handler.post(() -> result.notImplemented());
}
} catch (Exception e) {
handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null));
}
}
private void disableBatteryOptimization() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
private boolean isBatteryOptimizationDisabled() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
return pm.isIgnoringBatteryOptimizations(packageName);
}
}

View file

@ -0,0 +1,11 @@
package com.cakewallet.haven;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class Application extends FlutterApplication implements PluginRegistrantCallback {
@Override
public void registerWith(PluginRegistry registry) {}
}

View file

@ -0,0 +1,83 @@
package com.cakewallet.haven;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;
import android.content.Intent;
import android.net.Uri;
import android.os.PowerManager;
import android.provider.Settings;
import java.security.SecureRandom;
public class MainActivity extends FlutterFragmentActivity {
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel utilsChannel =
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
UTILS_CHANNEL);
utilsChannel.setMethodCallHandler(this::handle);
}
private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
Handler handler = new Handler(Looper.getMainLooper());
try {
switch (call.method) {
case "sec_random":
int count = call.argument("count");
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[count];
random.nextBytes(bytes);
handler.post(() -> result.success(bytes));
break;
case "disableBatteryOptimization":
disableBatteryOptimization();
handler.post(() -> result.success(null));
break;
case "isBatteryOptimizationDisabled":
boolean isDisabled = isBatteryOptimizationDisabled();
handler.post(() -> result.success(isDisabled));
break;
default:
handler.post(() -> result.notImplemented());
}
} catch (Exception e) {
handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null));
}
}
private void disableBatteryOptimization() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
private boolean isBatteryOptimizationDisabled() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
return pm.isIgnoringBatteryOptimizations(packageName);
}
}

View file

@ -0,0 +1,11 @@
package com.monero.app;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class Application extends FlutterApplication implements PluginRegistrantCallback {
@Override
public void registerWith(PluginRegistry registry) {}
}

View file

@ -0,0 +1,92 @@
package com.monero.app;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;
import android.content.Intent;
import android.net.Uri;
import android.os.PowerManager;
import android.provider.Settings;
import java.security.SecureRandom;
public class MainActivity extends FlutterFragmentActivity {
final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
boolean isAppSecure = false;
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
MethodChannel utilsChannel =
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),
UTILS_CHANNEL);
utilsChannel.setMethodCallHandler(this::handle);
}
private void handle(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
Handler handler = new Handler(Looper.getMainLooper());
try {
switch (call.method) {
case "sec_random":
int count = call.argument("count");
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[count];
random.nextBytes(bytes);
handler.post(() -> result.success(bytes));
break;
case "setIsAppSecure":
isAppSecure = call.argument("isAppSecure");
if (isAppSecure) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
break;
case "disableBatteryOptimization":
disableBatteryOptimization();
handler.post(() -> result.success(null));
break;
case "isBatteryOptimizationDisabled":
boolean isDisabled = isBatteryOptimizationDisabled();
handler.post(() -> result.success(isDisabled));
break;
default:
handler.post(() -> result.notImplemented());
}
} catch (Exception e) {
handler.post(() -> result.error("UNCAUGHT_ERROR", e.getMessage(), null));
}
}
private void disableBatteryOptimization() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
private boolean isBatteryOptimizationDisabled() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
return pm.isIgnoringBatteryOptimizations(packageName);
}
}

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/monero/aarch64-linux-android_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/wownero/aarch64-linux-android_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/zano/aarch64-linux-android_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/monero/armv7a-linux-androideabi_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/wownero/armv7a-linux-androideabi_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/zano/armv7a-linux-androideabi_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/monero/x86_64-linux-android_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/wownero/x86_64-linux-android_libwallet2_api_c.so

View file

@ -0,0 +1 @@
../../../../../../scripts/monero_c/release/zano/x86_64-linux-android_libwallet2_api_c.so

View file

@ -1,13 +0,0 @@
package com.cakewallet.cake_wallet
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine){
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="#000000"/> <!-- Dark background color -->
</item>
</layer-list>

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View file

@ -1,12 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
<item>
<color android:color="#FFFFFF"/> <!-- Light background color -->
</item>
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

View file

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cakewallet.cake_wallet">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->

View file

@ -1,18 +1,8 @@
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
@ -24,6 +14,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View file

@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
org.gradle.jvmargs=-Xmx4096M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

View file

@ -1,6 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
#Mon Apr 19 18:19:26 EEST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip

View file

@ -1,15 +1,26 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.1" apply false
id "org.jetbrains.kotlin.android" version "2.0.21" apply false
id "com.google.gms.google-services" version "4.3.8" apply false
}
include ":app"

1
assets/animation/anim1.json Executable file

File diff suppressed because one or more lines are too long

1
assets/animation/anim2.json Executable file

File diff suppressed because one or more lines are too long

1
assets/animation/anim3.json Executable file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,5 @@
-
uri: kaliumapi.appditto.com
path: /api
useSSL: true
is_default: true

View file

@ -0,0 +1,10 @@
-
uri: bitcoincash.stackwallet.com:50002
is_default: true
useSSL: true
-
uri: bch.aftrek.org:50002
useSSL: true
-
uri: node.minisatoshi.cash:50002
useSSL: true

View file

@ -0,0 +1,9 @@
-
uri: btc-electrum.cakewallet.com:50002
useSSL: true
isDefault: true
-
uri: electrs.cakewallet.com:50001
-
uri: fulcrum.sethforprivacy.com:50002
useSSL: true

View file

@ -0,0 +1,6 @@
-
uri: default-spv-nodes
is_default: true
-
uri: dcrd.sethforprivacy.com:9108
useSSL: true

View file

@ -1,2 +0,0 @@
-
uri: electrum.cakewallet.com:50002

View file

@ -0,0 +1,14 @@
-
uri: ethereum-rpc.publicnode.com
useSSL: true
isDefault: true
-
uri: eth.llamarpc.com
-
uri: rpc.flashbots.net
-
uri: eth-mainnet.public.blastapi.io
-
uri: eth.nownodes.io
-
uri: ethereum.publicnode.com

View file

@ -1,7 +1,7 @@
[
{
"question" : "Was ist der Unterschied zwischen verfügbarem Guthaben und vollständigem Guthaben?",
"answer" : "Nachdem Sie eine Transaktion getätigt oder Monero erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\nWenn Sie Monero senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Gleichgewicht\" sollte in 20 Minuten wieder normal sein.\n"
"answer" : "Nachdem Sie eine Transaktion getätigt oder Monero erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\nWenn Sie Monero senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Guthaben\" sollte in 20 Minuten wieder normal sein.\n"
},
{
"question" : "Wie sende ich Monero an eine Börse, für die eine Zahlungs-ID erforderlich ist?",
@ -12,24 +12,24 @@
"answer" : "Obwohl unser Support Sie bei diesem Problem nicht direkt unterstützen kann, ist es ein sehr häufiges Problem, mit dem die meisten Börsen vertraut sind. Wenden Sie sich einfach an den Support der Börse, erklären Sie, dass Sie vergessen haben, Ihre Zahlungs-ID anzugeben, und senden Sie ihnen dann Ihre Transaktions-ID als Nachweis. Sie finden die Transaktions-ID, indem Sie auf die Transaktion in Ihrem Wallet-Bildschirm tippen.\n"
},
{
"question" : "Was bedeuten \"Samen\" und \"Schlüssel\"?",
"answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihrer Brieftasche und ermöglichen es Ihnen, Münzen auszugeben und eingehende Transaktionen anzuzeigen.\nIhr Startwert ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Same und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\nGeben Sie niemals Ihren Samen oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Samen oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Samen und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihre Brieftasche wiederherstellen, wenn Sie Ihr Telefon verlieren.)\n"
"question" : "Was bedeuten \"Seed\" und \"Schlüssel\"?",
"answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihrer Brieftasche und ermöglichen es Ihnen, Münzen auszugeben und eingehende Transaktionen anzuzeigen.\nIhr Startwert ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Same und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\nGeben Sie niemals Ihren Seed oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Seed oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Seed und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihr Wallet wiederherstellen, wenn Sie Ihr Telefon verlieren.)\n"
},
{
"question" : "Wie viele Geldbörsen kann ich erstellen?",
"answer" : "Es gibt keine Grenzen! Sie können so viele Brieftaschen erstellen, wie Sie möchten.\n"
},
{
"question" : "Wie kann ich meine Brieftasche wiederherstellen?",
"answer" : "Tippen Sie auf das Menü •••, wählen Sie „Brieftaschen“ und dann „Brieftasche wiederherstellen“. Geben Sie dann Ihren Startwert (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrer Brieftasche ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Portemonnaie vollständig wiederherzustellen.\n"
"question" : "Wie kann ich mein Wallet wiederherstellen?",
"answer" : "Tippen Sie auf das Menü •••, wählen Sie „Wallest“ und dann „Wallet wiederherstellen“. Geben Sie dann Ihren Seed (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrem Wallet ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Wallet vollständig wiederherzustellen.\n"
},
{
"question" : "Was kann ich tun, wenn ich meinen Samen verliere?",
"answer" : "Wenn Sie Ihren Samen vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Cake Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines dieser Probleme auftritt, können wir leider nichts tun.\n"
"question" : "Was kann ich tun, wenn ich meinen Seed verliere?",
"answer" : "Wenn Sie Ihren Seed vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Cake Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines dieser Probleme auftritt, können wir leider nichts tun.\n"
},
{
"question" : "Sammeln Sie Informationen zu meiner Brieftasche?",
"answer" : "Cake Wallet sammelt oder zeichnet keine Informationen über Ihre Brieftasche auf. Ihre Privatsphäre ist uns wichtig.\n"
"question" : "Sammeln Sie Informationen zu meinem Wallet?",
"answer" : "Cake Wallet sammelt oder zeichnet keine Informationen über Ihr Wallet auf. Ihre Privatsphäre ist uns wichtig.\n"
},
{
"question" : "Kann ich eine Transaktion stornieren?",
@ -37,7 +37,7 @@
},
{
"question" : "Was sind Subadressen und wie verwende ich sie?",
"answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Münzen landen weiterhin in Ihrer Hauptbrieftasche, aber die Person, die die Münzen sendet, kann Ihre Hauptadresse nicht ermitteln. Unteradressen beginnen immer mit „8“.\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Monero erhalten, eine neue Unteradresse erstellen.\n"
"answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Münzen landen weiterhin in Ihrer Hauptwallet, aber die Person, die die Coins sendet, kann Ihre Hauptadresse nicht ermitteln. Unteradressen beginnen immer mit „8“.\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Monero erhalten, eine neue Unteradresse erstellen.\n"
},
{
"question" : "Was ist eine Transaktions-ID?",
@ -48,11 +48,11 @@
"answer" : "Wenn Sie Ihren Monero nicht erhalten haben, möchten Sie möglicherweise auf das Menü ••• tippen und auf Reconnect (Neu verbinden) klicken. Wenn dies nicht funktioniert, gehen Sie in das Einstellungsmenü, tippen Sie auf das Feld \"Aktueller Knoten\" und wählen Sie einen Knoten mit einem grünen Punkt daneben aus.\n"
},
{
"question" : "Ich habe in der App keine Münzen aus dem Umtausch erhalten. Was kann ich tun?",
"answer" : "Wenn Sie Probleme mit einem Austausch haben, wenden Sie sich am besten an den Austausch. Wir sind eine Partnerschaft mit XMR.TO, Morph und ChangeNow eingegangen. Rufen Sie daher am besten http://xmr.to, http://changenow.io oder http://morphtoken.com auf und wenden Sie sich an deren Support.\n"
"question" : "Ich habe in der App keine Coins aus dem Umtausch erhalten. Was kann ich tun?",
"answer" : "Wenn Sie Probleme mit einem Austausch haben, besteht die beste Option, den Austausch selbst zu kontaktieren. Wir haben uns mit Chechenow, Simpleswap, Sideshift und Trocador zusammengetan. Am besten wechseln Sie zu https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ und kontaktieren Sie ihre Unterstützung.\n"
},
{
"question" : "Wie kontaktiere ich den Cake Wallet-Support?",
"answer" : "Senden Sie eine E-Mail an support@cakewallet.com, schließen Sie sich dem Telegramm unter @cakewallet_bot an oder twittern Sie @CakeWalletXMR!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "I didn't receive my coins from the exchange in the app. What can I do?",
"answer" : "If you're having issues with an exchange, the best option is to contact the exchange itself. We're partnered with XMR.TO, Morph and ChangeNow, so your best bet is to go to http://xmr.to, http://changenow.io, or http://morphtoken.com and contact their support.\n"
"answer" : "If you're having issues with an exchange, the best option is to contact the exchange itself. We're partnered with ChangeNow, SimpleSwap, SideShift and Trocador. So your best bet is to go to https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ and contact their support.\n"
},
{
"question" : "How do I contact Cake Wallet support?",
"answer" : "Email support@cakewallet.com, join the Telegram at @cakewallet_bot, or tweet @CakeWalletXMR!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "No recibí mis monedas del intercambio en la aplicación. ¿Que puedo hacer?",
"answer" : "Si tiene problemas con un intercambio, la mejor opción es ponerse en contacto con el intercambio en sí. Estamos asociados con XMR.TO, Morph y ChangeNow, por lo que su mejor opción es ir a http://xmr.to, http://changenow.io o http://morphtoken.com y contactar a su soporte.\n"
"answer" : "Si tiene problemas con un intercambio, la mejor opción es comunicarse con el intercambio en sí. Estamos asociados con ChangeNow, SimpleSwap, SideShift y Trocador. Entonces, su mejor opción es ir a https://changenow.io, https://simplewap.io/, https://sideshift.ai/, https://trocador.app/ y contactar su soporte.\n"
},
{
"question" : "¿Cómo contacto al soporte de Cake Wallet?",
"answer" : "¡Envíe un correo electrónico a support@cakewallet.com, únase al Telegram en @cakewallet_bot o envíe un tweet a @CakeWalletXMR!\n"
}
]
]

59
assets/faq/faq_fr.json Normal file
View file

@ -0,0 +1,59 @@
[
{
"question" : "Quelle est la différence entre le solde disponible et le solde total ?",
"answer" : "Lorsque vous faites une transaction ou recevez des Monero, la transaction doit être confirmée. Au bout d'environ 20 minutes votre solde disponible devrait se mettre à jour !\nParfois, lorsque vous envoyez des Monero, votre solde disponible peut diminuer d'un montant supérieur à celui que vous avez envoyé. C'est normal, c'est une mesure destinée à augmenter votre intimité. Votre solde total devrait redevenir normal après environ 20 minutes.\n"
},
{
"question" : "Comment envoyer des Monero vers une plateforme d'échange qui nécessite un ID de paiement ?",
"answer" : "Appuyez sur le bouton envoyer de l'écran du Portefeuille (Wallet). Ensuite, copiez l'adresse de dépôt de la plateforme d'échange et collez là dans le champ adresse. Puis, copiez l'ID de paiement fourni par la plateforme d'échange et copiez le dans le champ ID de paiement. Enfin, entrez le montant que vous souhaitez envoyer et vous êtes fin prêt !\n"
},
{
"question" : "Que faire si j'oublie d'entrer l'ID de paiement quand j'envoie des Monero vers une plateforme d'échange ?",
"answer" : "Bien que notre service de support ne puisse pas vous aider directement pour ce type de souci, c'est un problème très courant que la plupart des plateformes d'échange ont l'habitude de gérer. Contactez simplement le support de la plateforme d'échange, expliquez que vous avez oublié d'inclure l'ID de paiement et envoyez leur l'ID de transaction comme preuve. Vous pouvez visualiser l'ID de transaction en tapant sur transaction sur l'écran de votre portefeuille (wallet).\n"
},
{
"question" : "Que signifient \"phrase secrète (seed)\" et \"clefs\" ?",
"answer" : "Vos clefs encodent l'information privée de votre portefeuille (wallet), ce sont elles qui permettent de dépenser vos fonds et de visualiser les transactions entrantes.\nVotre phrase secrète (seed) est simplement une version de votre clef privée sous une forme plus simple à recopier. Votre phrase secrète et vos clefs sont la même chose, juste sous des formes différentes !\nNE DONNEZ JAMAIS votre phrase secrète ou vos clefs à quiconque. Vos fonds seront dérobés si vous donnez votre phrase secrète ou vos clefs. Merci d'écrire cependant votre phrase secrète et de la stocker en lieu sûr (afin de vous permettre de restaurer votre portefeuille si vous perdez votre téléphone.)\n"
},
{
"question" : "Combien de portefeuilles (wallets) puis-je créer ?",
"answer" : "Il n'y a pas de limite ! Vous pouvez créer autant de portefeuilles (wallets) que vous le souhaitez.\n"
},
{
"question" : "Commen puis-je restarurer mon portefeuille (wallet) ?",
"answer" : "Appuyez sur le menu •••, sélectionnez Portefeuilles (Wallets), puis choisissez Restaurer un Portefeuille. Entrez alors votre phrase secrète (seed) (ou vos clefs), et de façon optionnelle une date antérieure à la première transaction de votre portefeuille (cela permettra d'accélérer le processus de synchronisation). Vous pourrez avoir besoin de maintenir l'application ouverte pendant 15 à 30 minutes afin de restaurer complètement votre portefeuille.\n"
},
{
"question" : "Que puis-je faire si je perds ma phrase secrète (seed) ?",
"answer" : "Si vous oubliez votre phrase secrète (seed), il y a des chances que vous l'ayez inscrite quelque part. Vérifiez vos notes et regardez sur votre ordinateur. Si vous ne parvenez pas à la retrouver, il est possible que vous ayez effectué une sauvegarde de Cake Wallet (dans ce cas vous pourrez restaurer d'après cette sauvegarde). Si aucune des ces options ne convient, malheureusement il n'y a plus rien à faire, vos fonds sont définitivement perdus.\n"
},
{
"question" : "Collectez vous des informations à propos de mon portefeuille (wallet) ?",
"answer" : "Cake Wallet NE COLLECTE PAS d'informations à propos de votre portefeuille (wallet). Nous sommes respectueux de votre intimité.\n"
},
{
"question" : "Est il possible d'annuler une transaction ?",
"answer" : "Malheureusement, dès qu'une transaction a été envoyée vers la blockchain, elle devient irréversible. Vous pouvez cependant annuler la transaction avant de l'envoyer, donc vérifiez toujours l'adresse avant d'envoyer une transaction.\n"
},
{
"question" : "Que sont les sous-adresses, et comment s'en servir ?",
"answer" : "Une sous-adresse est une adresse unique que vous pouvez générer à tout moment. Les montants envoyés vers cette adresse arrivent toujours dans votre portefeuille (wallet) principal, mais la personne qui vous envoie les fonds ne peut pas déterminer votre adresse principale. Les sous-adresses commencent par un 8.\nVous pouvez créer une nouvelle sous-adresse dans l'écran Réception en appuyant sur le + à côté du bouton Sous-Adresses. Entrez un nom pour la sous-adresse et appuyez sur Ajouter. Ensuite appuyez sur le nom de la sous-adresse quand vous souhaitez l'utiliser !\nSi vous êtres paranoïaque, vous devriez créer une nouvelle sous-adresse à chaque fois que vous voulez recevoir des Monero.\n"
},
{
"question" : "Qu'est-ce que l'ID de transaction ?",
"answer" : "Une empreinte (hash) de transaction, ou ID de transaction, est un moyen unique d'identifier une transaction. Chaque transaction a sa propre empreinte. Si vous deve fournir une empreinte de transaction à quelque'un, allez simplement sur l'écran principal du Portefeuille (Wallet), appuyez sur la transaction puis appuyez longuement sur la section du haut et sélectionnez Copier.\n"
},
{
"question" : "Je n'ai pas reçu mes XMR ! Que puis-je faire ?",
"answer" : "Si vous n'avez pas reçu vos Monero, appuyez sur le menu ••• et choisissez Reconnecter. Si cela ne règle pas le problème, allez dans le menu de réglage, appuyez sur le champ 'Nœud Courant' et sélectionnez un nœud avec un point vert.\n"
},
{
"question" : "Je n'ai pas reçu mes fonds en provenance de la plateforme d'échange dans l'application. Que puis-je faire ?",
"answer" : "Si vous rencontrez des problèmes avec un échange, la meilleure option est de contacter l'échange lui-même. Nous sommes en partenariat avec Changenow, Simpleswap, Sideshift et le Trocador. Donc, votre meilleur pari est d'aller sur https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ et contactez leur support.\n"
},
{
"question" : "Comment puis-je contacter le support de Cake Wallet ?",
"answer" : "Envoyez un email à support@cakewallet.com, rejoignez le groupe Telegram @cakewallet_bot, ou @CakeWalletXMR sur Twitter!\n"
}
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "मुझे ऐप में एक्सचेंज से मेरे सिक्के नहीं मिले। मैं क्या कर सकता हूँ?",
"answer" : "यदि आप एक एक्सचेंज के साथ समस्या कर रहे हैं, तो सबसे अच्छा विकल्प एक्सचेंज से संपर्क करना है। हम XMR.TO, Morph और ChangeNow के साथ भागीदारी कर रहे हैं, इसलिए आपका सबसे अच्छा दांव http://xmr.to, http://changenow.io, या http://morphtoken.com पर जाना है और उनके समर्थन से संपर्क करना है।\n"
"answer" : "यदि आप एक एक्सचेंज के साथ समस्याएं कर रहे हैं, तो सबसे अच्छा विकल्प एक्सचेंज से संपर्क करना है। हम चंगेनो, सिम्प्लेवैप, सिडशिफ्ट और ट्रोकैडर के साथ भागीदारी कर रहे हैं। तो आपका सबसे अच्छा दांव https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ पर जाना और उनके समर्थन से संपर्क करना है।\n"
},
{
"question" : "मैं केक वॉलेट से कैसे संपर्क करूं?",
"answer" : "ईमेल support@cakewallet.com, @cakewallet_bot पर टेलीग्राम में शामिल हों, या @CakeWalletXMR पर ट्वीट करें!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "アプリの取引所からコインを受け取りませんでした。 私に何ができる?",
"answer" : "取引所に問題がある場合、最良の選択肢は取引所自体に連絡することです。 XMR.TO、Morph、ChangeNowと提携しているため、最善の策はhttp//xmr.to、http//changenow.io、またはhttp://morphtoken.comにアクセスしてサポートに連絡することです。\n"
"answer" : "交換に問題がある場合、最良の選択肢は、交換自体に連絡することです。 Changenow、SimpleSwap、Sideshift、Trocadorと提携しています。したがって、あなたの最善の策は、https//changenow.io、https//simpleswap.io/、https//sideshift.ai/、https://trocador.app/に行くことです。\n"
},
{
"question" : "Cake Walletサポートに連絡するにはどうすればよいですか",
"answer" : "support@cakewallet.comにメールを送信するか、@cakewallet_botで電報に参加するか、@CakeWalletXMRにツイートしてください。\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "앱의 거래소에서 동전을받지 못했습니다. 내가 무엇을 할 수 있을지?",
"answer" : "교환에 문제가있는 경우 교환기에 연락하는 것이 가장 좋습니다. 우리는 XMR.TO, Morph 및 ChangeNow와 파트너 관계를 맺고 있으므로 가장 좋은 방법은 http://xmr.to, http://changenow.io 또는 http://morphtoken.com으로 이동하여 지원 부서에 문의하는 것입니다.\n"
"answer" : "교환에 문제가있는 경우 가장 좋은 선택은 Exchange 자체에 연락하는 것입니다. 우리는 Changenow, Simpleswap, Sideshift 및 Trocador와 파트너 관계를 맺고 있습니다. 따라서 가장 좋은 방법은 https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/로 이동하여 지원에 연락하는 것입니다.\n"
},
{
"question" : "Cake Wallet 지원팀에 연락하려면 어떻게해야합니까?",
"answer" : "support@cakewallet.com로 이메일을 보내거나 @cakewallet_bot에서 전보에 가입하거나 @CakeWalletXMR을 트윗하십시오!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "Ik heb mijn munten niet ontvangen van de beurs in de app. Wat kan ik doen?",
"answer" : "Als u problemen ondervindt met een uitwisseling, kunt u het beste contact opnemen met de uitwisseling zelf. We werken samen met XMR.TO, Morph en ChangeNow, dus u kunt het beste naar http://xmr.to, http://changenow.io of http://morphtoken.com gaan en contact opnemen met hun ondersteuning.\n"
"answer" : "Als u problemen heeft met een uitwisseling, is de beste optie om contact op te nemen met de uitwisseling zelf. We werken samen met ChangeNow, SimpleSwap, SideShift en Trocador. Dus het beste is om naar https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ te gaan en contact op te nemen met hun ondersteuning.\n"
},
{
"question" : "Hoe neem ik contact op met Cake Wallet-ondersteuning?",
"answer" : "E-mail support@cakewallet.com, word lid van het Telegram op @cakewallet_bot of tweet @CakeWalletXMR!\n"
}
]
]

View file

@ -13,7 +13,7 @@
},
{
"question" : "Co oznaczają słowa „seed” i „keys”?",
"answer" : "Twoje klucze kodują prywatne informacje w twoim portfelu i pozwalają wydać monety i zobaczyć przychodzące transakcje.\nTwoje ziarno to tylko wersja twojego klucza prywatnego napisana w sposób, który łatwiej Ci zapisać. Wasze nasiona i klucze są w rzeczywistości takie same, tylko w różnych formach!\nNigdy nie dawaj nikomu swojego ziarna ani kluczy. Twoje fundusze zostaną skradzione, jeśli wydasz swoje nasiona lub klucze. Zapisz jednak swoje ziarno i przechowuj je w bezpiecznym miejscu (pozwoli to przywrócić portfel, jeśli zgubisz telefon).\n"
"answer" : "Twoje klucze i fraza seed zawierają prywatne informacje o twoim portfelu i pozwalają wysyłać kryptowalutę oraz zobaczyć przychodzące transakcje.\nFraza „seed” to wersja twojego klucza prywatnego napisana w sposób, który łatwiej Ci zapisać. Wasze frazy seed i klucze są w rzeczywistości takie same, tylko w różnych formach zapisu!\nNigdy nie dawaj nikomu swojej frazy seed ani swoich kluczy. Twoje fundusze zostaną skradzione, jeśli upublicznisz frazę seed lub klucze. Zapisz jednak swoją frazę seed i przechowuj ją w bezpiecznym miejscu (pozwoli to przywrócić portfel, jeśli zgubisz telefon).\n"
},
{
"question" : "Ile portfeli mogę utworzyć?",
@ -24,11 +24,11 @@
"answer" : "Stuknij menu •••, wybierz „Portfele”, a następnie „Przywróć portfel”. Następnie wprowadź dane początkowe (lub klucze) i opcjonalnie wprowadź datę przed pierwszą transakcją w portfelu (przyspieszy to proces synchronizacji .) Może być konieczne pozostawienie aplikacji otwartej przez 15-30 minut, aby całkowicie przywrócić portfel.\n"
},
{
"question" : "Co mogę zrobić, jeśli stracę nasiona?",
"answer" : "Jeśli zapomniałeś o nasieniu, prawdopodobnie gdzieś je zapisałeś. Sprawdź swoje notatki i rozejrzyj się po komputerze. Jeśli nie możesz go nigdzie znaleźć, być może utworzono kopię zapasową Cake Wallet (w takim przypadku będziesz mógł przywrócić dane z tej kopii zapasowej). Jeśli żadna z tych czynności nie działa, niestety nic nie możemy zrobić.\n"
"question" : "Co mogę zrobić, jeśli zapomniałem frazę seed?",
"answer" : "Jeśli zapomniałeś swoją frazę seed, prawdopodobnie gdzieś je zapisałeś. Sprawdź swoje notatki i rozejrzyj się po komputerze. Jeśli nie możesz go nigdzie znaleźć, być może utworzono kopię zapasową Cake Wallet (w takim przypadku będziesz mógł przywrócić dane z tej kopii zapasowej). Jeśli żadna z tych czynności nie działa, niestety nic nie możemy zrobić.\n"
},
{
"question" : "Czy zbierasz jakieś informacje o moim portfelu?",
"question" : "Czy zbieracie jakieś informacje o moim portfelu?",
"answer" : "Portfel Cake NIE gromadzi ani nie rejestruje żadnych informacji o Twoim portfelu. Dbamy o Twoją prywatność.\n"
},
{
@ -37,7 +37,7 @@
},
{
"question" : "Co to są „podadresy” i jak z nich korzystać?",
"answer" : "Podadres jest w zasadzie unikalnym adresem, który można wygenerować w dowolnym momencie. Monety wysłane do niego nadal będą pojawiać się w głównym portfelu, ale osoba wysyłająca monety nie może podać Twojego głównego adresu. Podadresy zawsze zaczynają się od „8”.\nMożesz utworzyć nowy podadres na ekranie Odbieranie, dotykając „+” obok przycisku Podadresy. Wprowadź nazwę podadresu i dotknij „Dodaj”. Następnie dotknij nazwy podadresu, gdy chcesz go użyć!\nJeśli jesteś paranoikiem, prawdopodobnie za każdym razem, gdy otrzymasz Monero, powinieneś utworzyć nowy podadres.\n"
"answer" : "Podadres jest w unikalnym adresem, który można wygenerować w dowolnym momencie. Monety wysłane do niego nadal będą pojawiać się w głównym portfelu, ale osoba wysyłająca monety nie zna Twojego głównego adresu. Podadresy zawsze zaczynają się od „8”.\nMożesz utworzyć nowy podadres na ekranie Odbieranie, dotykając „+” obok przycisku Podadresy. Wprowadź nazwę podadresu i dotknij „Dodaj”. Następnie dotknij nazwy podadresu, gdy chcesz go użyć!\nJeśli jesteś paranoikiem, prawdopodobnie za każdym razem, gdy otrzymasz Monero, powinieneś utworzyć nowy podadres.\n"
},
{
"question" : "Co to jest ID transakcji?",
@ -49,10 +49,10 @@
},
{
"question" : "Nie otrzymałem moich monet z wymiany w aplikacji. Co mogę zrobić?",
"answer" : "Jeśli masz problemy z wymianą, najlepszym rozwiązaniem jest skontaktowanie się z samą giełdą. Współpracujemy z XMR.TO, Morph i ChangeNow, więc najlepiej postawić się na stronie http://xmr.to, http://changenow.io lub http://morphtoken.com i skontaktować się z ich wsparciem.\n"
"answer" : "Jeśli masz problemy z wymianą, najlepszą opcją jest skontaktowanie się z samą wymianą. Współpracujemy z Changenow, Simpleswap, Sideshift i Trocador. Więc najlepszym rozwiązaniem jest przejście na https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ i skontaktować się z ich obsługą.\n"
},
{
"question" : "Jak skontaktować się z obsługą Cake Wallet?",
"answer" : "Wyślij e-mail na adres support@cakewallet.com, dołącz do telegramu na @cakewallet_bot lub tweet @CakeWalletXMR!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "Não recebi minhas moedas da troca no aplicativo. O que eu posso fazer?",
"answer" : "Se você estiver tendo problemas com uma troca, a melhor opção é entrar em contato com a troca. Somos parceiros do XMR.TO, Morph e ChangeNow, portanto, sua melhor aposta é ir para http://xmr.to, http://changenow.io ou http://morphtoken.com e entrar em contato com o suporte deles.\n"
"answer" : "Se você estiver com problemas com uma troca, a melhor opção é entrar em contato com a própria troca. Estamos em parceria com ChangeNow, SimpleSwap, Sideshift e Trocador. Portanto, sua melhor aposta é ir para https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ e entre em contato com seu suporte.\n"
},
{
"question" : "Como entro em contato com o suporte da Cake Wallet?",
"answer" : "Envie um e-mail para support@cakewallet.com, participe do Telegram em @cakewallet_bot ou envie um tweet para @CakeWalletXMR!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "Я не получил свои монеты после обмена в приложении. Что я могу сделать?",
"answer" : "Если у вас возникли проблемы с обменом, лучше всего связаться с провайдером обмена. Мы сотрудничаем с XMR.TO, Morph и ChangeNow, поэтому вам лучше всего зайти на http://xmr.to, http://changenow.io или http://morphtoken.com и связаться с их поддержкой.\n"
"answer" : "Если у вас есть проблемы с обменом, лучший вариант - связаться с самой биржей. Мы сотрудничаем с Changenow, Simpleswap, SideShift и Trocador. Так что лучше всего пойти по адресу https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ и свяжитесь с их поддержкой.\n"
},
{
"question" : "Как мне связаться со службой поддержки Cake Wallet?",
"answer" : "По электронной почте support@cakewallet.com, присоединитесь к Telegram по адресу @cakewallet_bot или отправьте твит @CakeWalletXMR!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "Я не отримав свої монети після обміну в додатку. Що я можу зробити?",
"answer" : "Якщо у вас виникли проблеми з обміном, найкраще зв'язатися з провайдером обміну. Ми співпрацюємо з XMR.TO, Morph і ChangeNow, тому вам найкраще зайти на http://xmr.to, http://changenow.io або http://morphtoken.com і зв'язатися з їх підтримкою.\n"
"answer" : "Якщо у вас є проблеми з обміном, найкращим варіантом є зв’язок із самою біржею. Ми співпрацюємо з Changenow, Simplewap, Sideshift та Trocador. Тож найкраща ставка - перейти на https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ та звернутися до їх підтримки.\n"
},
{
"question" : "Як мені зв'язатися зі службою підтримки Cake Wallet?",
"answer" : "По електронній пошті support@cakewallet.com, приєднайтеся до Telegram за адресою @cakewallet_bot або надішліть твіт @CakeWalletXMR!\n"
}
]
]

View file

@ -49,10 +49,10 @@
},
{
"question" : "我没有从应用程序中的交易所收到硬币。 我能做什么?",
"answer" : "如果您对交易所有疑问,最好的选择是与交易所本身联系。 我们与XMR.TOMorph和ChangeNow合作因此最好的选择是访问http//xmr.to、http//changenow.io或http://morphtoken.com并与他们的支持部门联系。\n"
"answer" : "如果您对交易所有问题最好的选择是与交易所本身联系。我们与ChangeNowSimplesWapSideShift和Trocador合作。因此最好的选择是访问https://changenow.iohttps://simpleswap.io/https://sideshift.ai/https//trocador.app/并联系他们的支持。\n"
},
{
"question" : "如何联系蛋糕钱包支持?",
"answer" : "电子邮件support@cakewallet.com通过@cakewallet_bot加入电报或在@CakeWalletXMR上发布推文\n"
}
]
]

View file

@ -0,0 +1,4 @@
-
uri: nodes.havenprotocol.org:443
useSSL: true
is_default: true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/images/2fa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

View file

@ -0,0 +1,86 @@
<svg width="260" height="298" viewBox="0 0 260 298" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M119.655 6.27832C126.055 3.53578 133.272 3.45033 139.723 6.02148L140.345 6.27832L243.044 50.293C252.699 54.431 258.96 63.925 258.96 74.4297V128.542C258.96 175.815 236.309 220.2 198.085 247.94L197.18 248.593L145.264 285.676C136.276 292.096 124.25 292.197 115.167 285.978L114.736 285.676L62.8203 248.593C24.0499 220.899 1.04004 176.187 1.04004 128.542V74.4297C1.04004 64.0891 7.10644 54.7283 16.5059 50.4912L16.9561 50.293L119.655 6.27832Z" stroke="#708BF4" stroke-opacity="0.05" stroke-width="2.08"/>
<path d="M120.451 17.2793C126.358 14.7477 133.02 14.6687 138.975 17.042L139.549 17.2793L234.349 57.9082C243.261 61.7279 249.04 70.491 249.04 80.1875V130.138C249.04 173.775 228.131 214.745 192.848 240.352L192.012 240.954L144.089 275.185C135.792 281.111 124.692 281.204 116.308 275.463L115.911 275.185L67.9883 240.954C32.2001 215.391 10.96 174.118 10.96 130.138V80.1875C10.9601 70.6424 16.56 62.0019 25.2363 58.0908L25.6514 57.9082L120.451 17.2793Z" stroke="#708BF4" stroke-opacity="0.15" stroke-width="1.92"/>
<path d="M121.294 28.3906C126.68 26.0825 132.754 26.0099 138.183 28.1738L138.706 28.3906L225.605 65.6328C233.731 69.1153 239 77.1057 239 85.9463V131.733C239 171.381 220.152 208.625 188.301 232.109L186.774 233.218L142.846 264.596C135.282 269.999 125.161 270.083 117.517 264.849L117.154 264.596L73.2256 233.218C40.4513 209.807 21 172.01 21 131.733V85.9463C21 77.2438 26.1053 69.3657 34.0156 65.7998L34.3945 65.6328L121.294 28.3906Z" stroke="#708BF4" stroke-opacity="0.5" stroke-width="2"/>
<path d="M77.8584 226.327L117.794 254.852C125.096 260.068 134.904 260.068 142.206 254.852L182.141 226.327C212.176 204.874 230 170.238 230 133.329V91.7041C230 83.3035 224.994 75.7112 217.272 72.4021L138.272 38.5449C132.99 36.281 127.01 36.281 121.728 38.5449L42.7277 72.4021C35.0063 75.7112 30 83.3035 30 91.7041V133.329C30 170.238 47.8247 204.874 77.8584 226.327Z" fill="black"/>
<path d="M77.8584 226.327L117.794 254.852C125.096 260.068 134.904 260.068 142.206 254.852L182.141 226.327C212.176 204.874 230 170.238 230 133.329V91.7041C230 83.3035 224.994 75.7112 217.272 72.4021L138.272 38.5449C132.99 36.281 127.01 36.281 121.728 38.5449L42.7277 72.4021C35.0063 75.7112 30 83.3035 30 91.7041V133.329C30 170.238 47.8247 204.874 77.8584 226.327Z" fill="url(#paint0_linear_4774_13703)"/>
<path d="M123.479 42.6295C127.513 40.9005 132.063 40.8473 136.13 42.4684L136.521 42.6295L215.521 76.4869C221.609 79.0957 225.556 85.0812 225.556 91.7037V133.329C225.556 168.248 208.955 201.05 180.902 221.734L179.559 222.711L139.623 251.236C134.047 255.219 126.615 255.343 120.923 251.609L120.377 251.236L80.4414 222.711C51.5757 202.092 34.4443 168.802 34.4443 133.329V91.7037C34.4445 85.2882 38.1486 79.4709 43.9141 76.7418L44.4785 76.4869L123.479 42.6295Z" stroke="url(#paint1_linear_4774_13703)" stroke-width="8.88889"/>
<path d="M123.479 42.6295C127.513 40.9005 132.063 40.8473 136.13 42.4684L136.521 42.6295L215.521 76.4869C221.609 79.0957 225.556 85.0812 225.556 91.7037V133.329C225.556 168.248 208.955 201.05 180.902 221.734L179.559 222.711L139.623 251.236C134.047 255.219 126.615 255.343 120.923 251.609L120.377 251.236L80.4414 222.711C51.5757 202.092 34.4443 168.802 34.4443 133.329V91.7037C34.4445 85.2882 38.1486 79.4709 43.9141 76.7418L44.4785 76.4869L123.479 42.6295Z" stroke="url(#paint2_linear_4774_13703)" stroke-width="8.88889"/>
<path d="M123.479 42.6295C127.513 40.9005 132.063 40.8473 136.13 42.4684L136.521 42.6295L215.521 76.4869C221.609 79.0957 225.556 85.0812 225.556 91.7037V133.329C225.556 168.248 208.955 201.05 180.902 221.734L179.559 222.711L139.623 251.236C134.047 255.219 126.615 255.343 120.923 251.609L120.377 251.236L80.4414 222.711C51.5757 202.092 34.4443 168.802 34.4443 133.329V91.7037C34.4445 85.2882 38.1486 79.4709 43.9141 76.7418L44.4785 76.4869L123.479 42.6295Z" stroke="url(#paint3_linear_4774_13703)" stroke-width="8.88889"/>
<g filter="url(#filter0_ii_4774_13703)">
<path d="M77.8584 226.327L117.794 254.852C125.096 260.068 134.904 260.068 142.206 254.852L182.141 226.327C212.176 204.874 230 170.238 230 133.329V91.7041C230 83.3035 224.994 75.7112 217.272 72.4021L138.272 38.5449C132.99 36.281 127.01 36.281 121.728 38.5449L42.7277 72.4021C35.0063 75.7112 30 83.3035 30 91.7041V133.329C30 170.238 47.8247 204.874 77.8584 226.327Z" fill="black" fill-opacity="0.01"/>
</g>
<rect x="66.5" y="110.5" width="127" height="69.5833" rx="9.33333" fill="url(#paint4_linear_4774_13703)" fill-opacity="0.15" stroke="url(#paint5_linear_4774_13703)" stroke-width="3"/>
<g filter="url(#filter1_d_4774_13703)">
<path d="M85.027 155.008L85.4252 147.997L79.5392 151.857L77.4272 148.187L83.7113 145.037L77.4272 141.886L79.5392 138.216L85.4252 142.076L85.027 135.065H89.2338L88.8529 142.076L94.739 138.216L96.851 141.886L90.5495 145.037L96.851 148.187L94.739 151.857L88.8529 147.997L89.2338 155.008H85.027ZM113.447 155.008L113.845 147.997L107.959 151.857L105.847 148.187L112.131 145.037L105.847 141.886L107.959 138.216L113.845 142.076L113.447 135.065H117.654L117.273 142.076L123.159 138.216L125.271 141.886L118.969 145.037L125.271 148.187L123.159 151.857L117.273 147.997L117.654 155.008H113.447ZM141.866 155.008L142.265 147.997L136.379 151.857L134.267 148.187L140.551 145.037L134.267 141.886L136.379 138.216L142.265 142.076L141.866 135.065H146.073L145.692 142.076L151.578 138.216L153.69 141.886L147.389 145.037L153.69 148.187L151.578 151.857L145.692 147.997L146.073 155.008H141.866ZM170.286 155.008L170.684 147.997L164.798 151.857L162.686 148.187L168.971 145.037L162.686 141.886L164.798 138.216L170.684 142.076L170.286 135.065H174.493L174.112 142.076L179.998 138.216L182.11 141.886L175.809 145.037L182.11 148.187L179.998 151.857L174.112 147.997L174.493 155.008H170.286Z" fill="#EFEFF8"/>
</g>
<path d="M164.716 223.419H215.284C220.845 223.419 224.31 217.386 221.508 212.583L196.224 169.239C193.443 164.473 186.556 164.473 183.776 169.239L158.492 212.583C155.69 217.386 159.155 223.419 164.716 223.419Z" fill="#D9D9D9"/>
<path d="M164.716 223.419H215.284C220.845 223.419 224.31 217.386 221.508 212.583L196.224 169.239C193.443 164.473 186.556 164.473 183.776 169.239L158.492 212.583C155.69 217.386 159.155 223.419 164.716 223.419Z" fill="url(#paint6_linear_4774_13703)"/>
<path d="M164.716 223.419H215.284C220.845 223.419 224.31 217.386 221.508 212.583L196.224 169.239C193.443 164.473 186.556 164.473 183.776 169.239L158.492 212.583C155.69 217.386 159.155 223.419 164.716 223.419Z" stroke="#312938" stroke-width="3.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M164.716 223.419H215.284C220.845 223.419 224.31 217.386 221.508 212.583L196.224 169.239C193.443 164.473 186.556 164.473 183.776 169.239L158.492 212.583C155.69 217.386 159.155 223.419 164.716 223.419Z" stroke="url(#paint7_linear_4774_13703)" stroke-width="3.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M164.716 223.419H215.284C220.845 223.419 224.31 217.386 221.508 212.583L196.224 169.239C193.443 164.473 186.556 164.473 183.776 169.239L158.492 212.583C155.69 217.386 159.155 223.419 164.716 223.419Z" stroke="url(#paint8_linear_4774_13703)" stroke-width="3.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M189.925 208.897H189.961M189.925 198.089V187.281" stroke="#312938" stroke-width="7.20545" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<filter id="filter0_ii_4774_13703" x="30" y="36.8469" width="200" height="221.917" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend mode="plus-lighter" in2="shape" result="effect1_innerShadow_4774_13703"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_4774_13703" result="effect2_innerShadow_4774_13703"/>
</filter>
<filter id="filter1_d_4774_13703" x="68.1106" y="125.748" width="123.316" height="38.5765" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="4.65833"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.937255 0 0 0 0 0.937255 0 0 0 0 0.972549 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4774_13703"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4774_13703" result="shape"/>
</filter>
<linearGradient id="paint0_linear_4774_13703" x1="130" y1="34.9996" x2="130" y2="263.571" gradientUnits="userSpaceOnUse">
<stop stop-color="#19233C"/>
<stop offset="1" stop-color="#1647C3"/>
</linearGradient>
<linearGradient id="paint1_linear_4774_13703" x1="130" y1="34.9996" x2="130" y2="263.571" gradientUnits="userSpaceOnUse">
<stop stop-color="#C1F2FF"/>
<stop offset="0.42" stop-color="#2077F8"/>
<stop offset="0.700262" stop-color="#000F4D"/>
</linearGradient>
<linearGradient id="paint2_linear_4774_13703" x1="130" y1="34.9996" x2="130" y2="263.571" gradientUnits="userSpaceOnUse">
<stop stop-color="#C1F2FF"/>
<stop offset="0.700262" stop-color="#718CF5"/>
</linearGradient>
<linearGradient id="paint3_linear_4774_13703" x1="130" y1="34.9996" x2="130" y2="263.571" gradientUnits="userSpaceOnUse">
<stop stop-color="#D8E3FF"/>
<stop offset="0.700262" stop-color="#718CF5"/>
</linearGradient>
<linearGradient id="paint4_linear_4774_13703" x1="130" y1="109" x2="130" y2="181.583" gradientUnits="userSpaceOnUse">
<stop stop-color="#5590FF"/>
<stop offset="1" stop-color="#5590FF" stop-opacity="0.5"/>
</linearGradient>
<linearGradient id="paint5_linear_4774_13703" x1="190.695" y1="181.583" x2="69.3054" y2="109" gradientUnits="userSpaceOnUse">
<stop stop-color="#EFEFF8" stop-opacity="0"/>
<stop offset="1" stop-color="#EFEFF8"/>
</linearGradient>
<linearGradient id="paint6_linear_4774_13703" x1="190" y1="165.664" x2="190.433" y2="233.264" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFC414"/>
<stop offset="1" stop-color="#FF9500"/>
</linearGradient>
<linearGradient id="paint7_linear_4774_13703" x1="190" y1="165.664" x2="190" y2="223.419" gradientUnits="userSpaceOnUse">
<stop stop-color="#5C486E"/>
<stop offset="1" stop-color="#312938"/>
</linearGradient>
<linearGradient id="paint8_linear_4774_13703" x1="190" y1="165.664" x2="190" y2="223.419" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#EBD4FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,101 @@
<svg width="260" height="298" viewBox="0 0 260 298" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M119.655 6.2793C126.055 3.53675 133.272 3.4513 139.723 6.02246L140.345 6.2793L243.044 50.2939C252.699 54.432 258.96 63.9259 258.96 74.4307V128.543C258.96 175.816 236.309 220.201 198.085 247.941L197.18 248.594L145.264 285.677C136.276 292.097 124.25 292.198 115.167 285.979L114.736 285.677L62.8203 248.594C24.0499 220.9 1.04004 176.188 1.04004 128.543V74.4307C1.04004 64.09 7.10644 54.7293 16.5059 50.4922L16.9561 50.2939L119.655 6.2793Z" stroke="#4A98DC" stroke-opacity="0.05" stroke-width="2.08"/>
<path d="M120.451 17.2803C126.358 14.7487 133.02 14.6696 138.975 17.043L139.549 17.2803L234.349 57.9092C243.261 61.7289 249.04 70.492 249.04 80.1885V130.139C249.04 173.775 228.131 214.746 192.848 240.353L192.012 240.955L144.089 275.186C135.792 281.112 124.692 281.205 116.308 275.464L115.911 275.186L67.9883 240.955C32.2001 215.392 10.96 174.119 10.96 130.139V80.1885C10.9601 70.6434 16.56 62.0028 25.2363 58.0918L25.6514 57.9092L120.451 17.2803Z" stroke="#4B98DC" stroke-opacity="0.15" stroke-width="1.92"/>
<path d="M121.294 28.3916C126.68 26.0835 132.754 26.0109 138.183 28.1748L138.706 28.3916L225.605 65.6338C233.731 69.1163 239 77.1066 239 85.9473V131.734C239 171.382 220.152 208.626 188.301 232.11L186.774 233.219L142.846 264.597C135.282 270 125.161 270.084 117.517 264.85L117.154 264.597L73.2256 233.219C40.4513 209.808 21 172.011 21 131.734V85.9473C21 77.2448 26.1053 69.3666 34.0156 65.8008L34.3945 65.6338L121.294 28.3916Z" stroke="#4895DB" stroke-opacity="0.35" stroke-width="2"/>
<path d="M77.8584 226.328L117.794 254.853C125.096 260.069 134.904 260.069 142.206 254.853L182.141 226.328C212.176 204.875 230 170.239 230 133.33V91.7051C230 83.3045 224.994 75.7122 217.272 72.403L138.272 38.5459C132.99 36.2819 127.01 36.2819 121.728 38.5459L42.7277 72.403C35.0063 75.7122 30 83.3045 30 91.7051V133.33C30 170.239 47.8247 204.875 77.8584 226.328Z" fill="black"/>
<path d="M77.8584 226.328L117.794 254.853C125.096 260.069 134.904 260.069 142.206 254.853L182.141 226.328C212.176 204.875 230 170.239 230 133.33V91.7051C230 83.3045 224.994 75.7122 217.272 72.403L138.272 38.5459C132.99 36.2819 127.01 36.2819 121.728 38.5459L42.7277 72.403C35.0063 75.7122 30 83.3045 30 91.7051V133.33C30 170.239 47.8247 204.875 77.8584 226.328Z" fill="url(#paint0_linear_4774_13798)"/>
<path d="M77.8584 226.328L117.794 254.853C125.096 260.069 134.904 260.069 142.206 254.853L182.141 226.328C212.176 204.875 230 170.239 230 133.33V91.7051C230 83.3045 224.994 75.7122 217.272 72.403L138.272 38.5459C132.99 36.2819 127.01 36.2819 121.728 38.5459L42.7277 72.403C35.0063 75.7122 30 83.3045 30 91.7051V133.33C30 170.239 47.8247 204.875 77.8584 226.328Z" fill="url(#paint1_linear_4774_13798)"/>
<path d="M77.8584 226.328L117.794 254.853C125.096 260.069 134.904 260.069 142.206 254.853L182.141 226.328C212.176 204.875 230 170.239 230 133.33V91.7051C230 83.3045 224.994 75.7122 217.272 72.403L138.272 38.5459C132.99 36.2819 127.01 36.2819 121.728 38.5459L42.7277 72.403C35.0063 75.7122 30 83.3045 30 91.7051V133.33C30 170.239 47.8247 204.875 77.8584 226.328Z" fill="url(#paint2_linear_4774_13798)"/>
<path d="M77.8584 226.328L117.794 254.853C125.096 260.069 134.904 260.069 142.206 254.853L182.141 226.328C212.176 204.875 230 170.239 230 133.33V91.7051C230 83.3045 224.994 75.7122 217.272 72.403L138.272 38.5459C132.99 36.2819 127.01 36.2819 121.728 38.5459L42.7277 72.403C35.0063 75.7122 30 83.3045 30 91.7051V133.33C30 170.239 47.8247 204.875 77.8584 226.328Z" fill="url(#paint3_linear_4774_13798)"/>
<path d="M123.479 42.6305C127.513 40.9015 132.063 40.8482 136.13 42.4693L136.521 42.6305L215.521 76.4879C221.609 79.0967 225.556 85.0821 225.556 91.7047V133.33C225.556 168.249 208.955 201.051 180.902 221.735L179.559 222.712L139.623 251.237C134.047 255.22 126.615 255.344 120.923 251.61L120.377 251.237L80.4414 222.712C51.5757 202.093 34.4443 168.803 34.4443 133.33V91.7047C34.4445 85.2892 38.1486 79.4719 43.9141 76.7428L44.4785 76.4879L123.479 42.6305Z" stroke="url(#paint4_linear_4774_13798)" stroke-width="8.88889"/>
<path d="M123.479 42.6305C127.513 40.9015 132.063 40.8482 136.13 42.4693L136.521 42.6305L215.521 76.4879C221.609 79.0967 225.556 85.0821 225.556 91.7047V133.33C225.556 168.249 208.955 201.051 180.902 221.735L179.559 222.712L139.623 251.237C134.047 255.22 126.615 255.344 120.923 251.61L120.377 251.237L80.4414 222.712C51.5757 202.093 34.4443 168.803 34.4443 133.33V91.7047C34.4445 85.2892 38.1486 79.4719 43.9141 76.7428L44.4785 76.4879L123.479 42.6305Z" stroke="url(#paint5_linear_4774_13798)" stroke-width="8.88889"/>
<path d="M123.479 42.6305C127.513 40.9015 132.063 40.8482 136.13 42.4693L136.521 42.6305L215.521 76.4879C221.609 79.0967 225.556 85.0821 225.556 91.7047V133.33C225.556 168.249 208.955 201.051 180.902 221.735L179.559 222.712L139.623 251.237C134.047 255.22 126.615 255.344 120.923 251.61L120.377 251.237L80.4414 222.712C51.5757 202.093 34.4443 168.803 34.4443 133.33V91.7047C34.4445 85.2892 38.1486 79.4719 43.9141 76.7428L44.4785 76.4879L123.479 42.6305Z" stroke="url(#paint6_linear_4774_13798)" stroke-width="8.88889"/>
<path d="M123.479 42.6305C127.513 40.9015 132.063 40.8482 136.13 42.4693L136.521 42.6305L215.521 76.4879C221.609 79.0967 225.556 85.0821 225.556 91.7047V133.33C225.556 168.249 208.955 201.051 180.902 221.735L179.559 222.712L139.623 251.237C134.047 255.22 126.615 255.344 120.923 251.61L120.377 251.237L80.4414 222.712C51.5757 202.093 34.4443 168.803 34.4443 133.33V91.7047C34.4445 85.2892 38.1486 79.4719 43.9141 76.7428L44.4785 76.4879L123.479 42.6305Z" stroke="url(#paint7_linear_4774_13798)" stroke-width="8.88889"/>
<g filter="url(#filter0_ii_4774_13798)">
<path d="M77.8584 226.328L117.794 254.853C125.096 260.069 134.904 260.069 142.206 254.853L182.141 226.328C212.176 204.875 230 170.239 230 133.33V91.7051C230 83.3045 224.994 75.7122 217.272 72.403L138.272 38.5459C132.99 36.2819 127.01 36.2819 121.728 38.5459L42.7277 72.403C35.0063 75.7122 30 83.3045 30 91.7051V133.33C30 170.239 47.8247 204.875 77.8584 226.328Z" fill="black" fill-opacity="0.01"/>
</g>
<rect x="67" y="111" width="126" height="68.5833" rx="8.83333" fill="url(#paint8_linear_4774_13798)" stroke="url(#paint9_linear_4774_13798)" stroke-width="4"/>
<g filter="url(#filter1_d_4774_13798)">
<path d="M85.027 155.008L85.4252 147.997L79.5392 151.857L77.4272 148.187L83.7113 145.037L77.4272 141.886L79.5392 138.216L85.4252 142.076L85.027 135.065H89.2338L88.8529 142.076L94.739 138.216L96.851 141.886L90.5495 145.037L96.851 148.187L94.739 151.857L88.8529 147.997L89.2338 155.008H85.027ZM113.447 155.008L113.845 147.997L107.959 151.857L105.847 148.187L112.131 145.037L105.847 141.886L107.959 138.216L113.845 142.076L113.447 135.065H117.654L117.273 142.076L123.159 138.216L125.271 141.886L118.969 145.037L125.271 148.187L123.159 151.857L117.273 147.997L117.654 155.008H113.447ZM141.866 155.008L142.265 147.997L136.379 151.857L134.267 148.187L140.551 145.037L134.267 141.886L136.379 138.216L142.265 142.076L141.866 135.065H146.073L145.692 142.076L151.578 138.216L153.69 141.886L147.389 145.037L153.69 148.187L151.578 151.857L145.692 147.997L146.073 155.008H141.866ZM170.286 155.008L170.684 147.997L164.798 151.857L162.686 148.187L168.971 145.037L162.686 141.886L164.798 138.216L170.684 142.076L170.286 135.065H174.493L174.112 142.076L179.998 138.216L182.11 141.886L175.809 145.037L182.11 148.187L179.998 151.857L174.112 147.997L174.493 155.008H170.286Z" fill="#2C71CC"/>
</g>
<path d="M164.716 223.418H215.284C220.845 223.418 224.31 217.386 221.508 212.582L196.224 169.239C193.443 164.472 186.556 164.472 183.776 169.239L158.492 212.582C155.69 217.386 159.155 223.418 164.716 223.418Z" fill="#D9D9D9"/>
<path d="M164.716 223.418H215.284C220.845 223.418 224.31 217.386 221.508 212.582L196.224 169.239C193.443 164.472 186.556 164.472 183.776 169.239L158.492 212.582C155.69 217.386 159.155 223.418 164.716 223.418Z" fill="url(#paint10_linear_4774_13798)"/>
<path d="M164.716 223.418H215.284C220.845 223.418 224.31 217.386 221.508 212.582L196.224 169.239C193.443 164.472 186.556 164.472 183.776 169.239L158.492 212.582C155.69 217.386 159.155 223.418 164.716 223.418Z" stroke="#312938" stroke-width="3.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M164.716 223.418H215.284C220.845 223.418 224.31 217.386 221.508 212.582L196.224 169.239C193.443 164.472 186.556 164.472 183.776 169.239L158.492 212.582C155.69 217.386 159.155 223.418 164.716 223.418Z" stroke="url(#paint11_linear_4774_13798)" stroke-width="3.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M189.925 208.896H189.961M189.925 198.088V187.28" stroke="#312938" stroke-width="7.20545" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<filter id="filter0_ii_4774_13798" x="30" y="36.8479" width="200" height="221.917" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_4774_13798"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.022328 0 0 0 0 0.298259 0 0 0 0 0.663462 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_4774_13798" result="effect2_innerShadow_4774_13798"/>
</filter>
<filter id="filter1_d_4774_13798" x="68.1106" y="125.748" width="123.316" height="38.5765" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="4.65833"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.172549 0 0 0 0 0.443137 0 0 0 0 0.8 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4774_13798"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4774_13798" result="shape"/>
</filter>
<linearGradient id="paint0_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#002A52"/>
<stop offset="1" stop-color="#0652DF"/>
</linearGradient>
<linearGradient id="paint1_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#19233C"/>
<stop offset="1" stop-color="#144CD8"/>
</linearGradient>
<linearGradient id="paint2_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#19233C"/>
<stop offset="1" stop-color="#1647C3"/>
</linearGradient>
<linearGradient id="paint3_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop offset="0.144488" stop-color="#FAFAFA"/>
<stop offset="1" stop-color="#72AAFF"/>
</linearGradient>
<linearGradient id="paint4_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#C1F2FF"/>
<stop offset="0.42" stop-color="#2077F8"/>
<stop offset="0.700262" stop-color="#000F4D"/>
</linearGradient>
<linearGradient id="paint5_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#C1F2FF"/>
<stop offset="0.700262" stop-color="#718CF5"/>
</linearGradient>
<linearGradient id="paint6_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#D8E3FF"/>
<stop offset="0.700262" stop-color="#718CF5"/>
</linearGradient>
<linearGradient id="paint7_linear_4774_13798" x1="130" y1="35.0006" x2="130" y2="263.572" gradientUnits="userSpaceOnUse">
<stop stop-color="#68BEEF"/>
<stop offset="0.700262" stop-color="#2C71CC"/>
</linearGradient>
<linearGradient id="paint8_linear_4774_13798" x1="147.5" y1="170" x2="69.5" y2="100" gradientUnits="userSpaceOnUse">
<stop offset="0.0455724" stop-color="white" stop-opacity="0"/>
<stop offset="1" stop-color="white" stop-opacity="0.5"/>
</linearGradient>
<linearGradient id="paint9_linear_4774_13798" x1="65" y1="109" x2="195" y2="185.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#4794DA"/>
<stop offset="0.954879" stop-color="#72AAFF" stop-opacity="0.2"/>
</linearGradient>
<linearGradient id="paint10_linear_4774_13798" x1="190" y1="165.664" x2="190.433" y2="233.264" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFC414"/>
<stop offset="1" stop-color="#FF9500"/>
</linearGradient>
<linearGradient id="paint11_linear_4774_13798" x1="190" y1="165.664" x2="190" y2="223.418" gradientUnits="userSpaceOnUse">
<stop stop-color="#5C486E"/>
<stop offset="1" stop-color="#312938"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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