Rebase node-sqlite-migration onto dev
Squashed migration of node Hive→SQLite, default-node handling, isPow/proxy support, arbitrum node updates, and related fixes. Replays node-sqlite-migration on top of current dev without the amount-refactor merge that the original branch carried. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Omar committed
May 26, 2026 at 17:04 UTC
ac05166e956ba09e242144a31a96670aea3f382d
72 files changed
+1201
-1052
assets/arbitrum_node_list.yml
+5
-2
@@ -1,12 +1,15 @@
1
-
2
uri: arbitrum.nownodes.io
3
- is_default: true
3
useSSL: true
4
isEnabledForAutoSwitching: true
5
+ label: "NOWNodes"
6
-
7
uri: arbitrum.drpc.org
8
useSSL: true
9
+ label: "dRPC"
10
-
11
uri: arbitrum-one-rpc.publicnode.com
12
useSSL: true
12
- isEnabledForAutoSwitching: true
\ No newline at end of file
13
+ isDefault: true
14
+ isEnabledForAutoSwitching: true
15
+ label: "PublicNode"
\ No newline at end of file
assets/base_node_list.yml
+6
-2
@@ -1,15 +1,19 @@
1
-
2
uri: base.nownodes.io
3
+ isDefault: true
4
useSSL: true
5
isEnabledForAutoSwitching: true
6
+ label: "NOWNodes"
7
-
8
uri: base.llamarpc.com
9
useSSL: true
10
+ label: "LlamaNodes"
11
-
12
uri: base-rpc.publicnode.com
10
- is_default: true
13
useSSL: true
14
isEnabledForAutoSwitching: true
15
+ label: "PublicNode"
16
-
17
uri: 1rpc.io/base
15
- useSSL: true
\ No newline at end of file
18
+ useSSL: true
19
+ label: "1RPC"
\ No newline at end of file
assets/bitcoin_cash_electrum_server_list.yml
+3
-4
@@ -1,12 +1,11 @@
1
-
2
uri: bitcoincash.stackwallet.com:50002
3
- is_default: true
3
+ isDefault: true
4
useSSL: true
5
isEnabledForAutoSwitching: true
6
+ label: "Stack Wallet"
7
-
8
uri: bch.aftrek.org:50002
9
useSSL: true
10
isEnabledForAutoSwitching: true
10
--
11
- uri: node.minisatoshi.cash:50002
12
- useSSL: true
11
+ label: "Aftrek"
assets/bitcoin_electrum_server_list.yml
+7
@@ -2,14 +2,21 @@
2
uri: btc-electrum.cakewallet.com:50002
3
useSSL: true
4
isDefault: true
5
+ isOfficial: true
6
isEnabledForAutoSwitching: true
7
+ label: "Cake Wallet Electrum"
8
-
9
uri: electrs.cakewallet.com:50001
10
+ isOfficial: true
11
+ label: "Cake Wallet Electrs"
12
-
13
uri: fulcrum.sethforprivacy.com:50002
14
useSSL: true
15
isEnabledForAutoSwitching: true
16
+ label: "Seth For Privacy"
17
-
18
uri: electrum.cakewallet.com:50002
19
+ isOfficial: true
20
useSSL: true
21
isEnabledForAutoSwitching: true
22
+ label: "Cake Wallet (Legacy)"
assets/bsc_node_list.yml
+7
@@ -3,26 +3,33 @@
3
useSSL: true
4
isDefault: true
5
isEnabledForAutoSwitching: true
6
+ label: "BNBChain"
7
-
8
uri: bsc-dataseed2.bnbchain.org
9
useSSL: true
10
isEnabledForAutoSwitching: true
11
+ label: "BNBChain #2"
12
-
13
uri: bsc-dataseed.nariox.org
14
useSSL: true
15
isEnabledForAutoSwitching: true
16
+ label: "Nariox"
17
-
18
uri: bsc-dataseed.defibit.io
19
useSSL: true
20
isEnabledForAutoSwitching: true
21
+ label: "DeFibit"
22
-
23
uri: bsc-dataseed.ninicoin.io
24
useSSL: true
25
isEnabledForAutoSwitching: true
26
+ label: "NiniCoin"
27
-
28
uri: bsc.nodereal.io
29
useSSL: true
30
isEnabledForAutoSwitching: true
31
+ label: "NodeReal"
32
-
33
uri: bsc-dataseed-public.bnbchain.org
34
useSSL: true
35
+ label: "BNBChain Public"
\ No newline at end of file
assets/decred_node_list.yml
+4
-2
@@ -1,8 +1,10 @@
1
-
2
uri: default-spv-nodes
3
- is_default: true
3
+ isDefault: true
4
isEnabledForAutoSwitching: true
5
+ label: "Decred"
6
-
7
uri: dcrd.sethforprivacy.com:9108
8
useSSL: true
8
- isEnabledForAutoSwitching: true
\ No newline at end of file
9
+ isEnabledForAutoSwitching: true
10
+ label: "Seth For Privacy"
\ No newline at end of file
assets/dogecoin_electrum_server_list.yml
+5
-2
@@ -1,12 +1,15 @@
1
-
2
uri: dogecoin.stackwallet.com:50022
3
- is_default: true
3
+ isDefault: true
4
useSSL: true
5
isEnabledForAutoSwitching: true
6
+ label: "Stack Wallet"
7
-
8
uri: doge.aftrek.org:50002
9
useSSL: true
10
isEnabledForAutoSwitching: true
11
+ label: "Aftrek"
12
-
13
uri: electrum1.cipig.net:20060
12
- useSSL: true
\ No newline at end of file
14
+ useSSL: true
15
+ label: "Cipig"
\ No newline at end of file
assets/ethereum_server_list.yml
+5
-2
@@ -3,18 +3,21 @@
3
useSSL: true
4
isDefault: true
5
isEnabledForAutoSwitching: true
6
+ label: "PublicNode"
7
-
8
uri: eth.llamarpc.com
9
useSSL: true
10
+ label: "LlamaNodes"
11
-
12
uri: rpc.flashbots.net
13
useSSL: true
14
+ label: "Flashbots"
15
-
16
uri: eth-mainnet.public.blastapi.io
17
useSSL: true
18
+ label: "Blast"
19
-
20
uri: eth.nownodes.io
21
useSSL: true
22
isEnabledForAutoSwitching: true
19
--
20
- uri: ethereum.publicnode.com
\ No newline at end of file
23
+ label: "NOWNodes"
\ No newline at end of file
assets/haven_node_list.yml
+1
-1
@@ -1,4 +1,4 @@
1
-
2
uri: nodes.havenprotocol.org:443
3
useSSL: true
4
- is_default: true
\ No newline at end of file
4
+ isDefault: true
\ No newline at end of file
assets/lightning_deposit_help.svg
deleted
-99
@@ -1,99 +0,0 @@
1
-<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <g clip-path="url(#clip0_14800_609868)">
3
- <g opacity="0.5">
4
- <path d="M65.6689 41.3975C61.2164 59.2548 43.128 70.1225 25.2667 65.6694C7.41273 61.2173 -3.45614 43.1298 0.998503 25.2735C5.44898 7.41416 23.5374 -3.45459 41.3934 0.997495C59.2537 5.44958 70.1215 23.5392 65.6689 41.3975Z" fill="url(#paint0_linear_14800_609868)"/>
5
- <path d="M65.6689 41.3975C61.2164 59.2548 43.128 70.1225 25.2667 65.6694C7.41273 61.2173 -3.45614 43.1298 0.998503 25.2735C5.44898 7.41416 23.5374 -3.45459 41.3934 0.997495C59.2537 5.44958 70.1215 23.5392 65.6689 41.3975Z" fill="url(#paint1_linear_14800_609868)"/>
6
- <path d="M0.998503 25.2735C5.44902 7.41421 23.5374 -3.45458 41.3934 0.997489C59.2536 5.44957 70.1214 23.5392 65.669 41.3975L65.5622 41.8149C60.9703 59.2852 43.2701 69.9194 25.6853 65.7709L25.2667 65.6693C7.41273 61.2173 -3.45614 43.1298 0.998503 25.2735ZM41.0708 2.29124C23.9295 -1.9826 6.56484 8.45112 2.29239 25.5959V25.5964C-1.98393 42.7381 8.44993 60.1016 25.5892 64.3756C42.7359 68.6506 60.1007 58.2178 64.3751 41.0751C68.6495 23.9311 58.2162 6.56514 41.0708 2.29124Z" fill="url(#paint2_linear_14800_609868)"/>
7
- <path d="M0.998503 25.2735C5.44902 7.41421 23.5374 -3.45458 41.3934 0.997489C59.2536 5.44957 70.1214 23.5392 65.669 41.3975L65.5622 41.8149C60.9703 59.2852 43.2701 69.9194 25.6853 65.7709L25.2667 65.6693C7.41273 61.2173 -3.45614 43.1298 0.998503 25.2735ZM41.0708 2.29124C23.9295 -1.9826 6.56484 8.45112 2.29239 25.5959V25.5964C-1.98393 42.7381 8.44993 60.1016 25.5892 64.3756C42.7359 68.6506 60.1007 58.2178 64.3751 41.0751C68.6495 23.9311 58.2162 6.56514 41.0708 2.29124Z" fill="url(#paint3_linear_14800_609868)"/>
8
- <path d="M0.998503 25.2735C5.44902 7.41421 23.5374 -3.45458 41.3934 0.997489C59.2536 5.44957 70.1214 23.5392 65.669 41.3975L65.5622 41.8149C60.9703 59.2852 43.2701 69.9194 25.6853 65.7709L25.2667 65.6693C7.41273 61.2173 -3.45614 43.1298 0.998503 25.2735ZM41.0708 2.29124C23.9295 -1.9826 6.56484 8.45112 2.29239 25.5959V25.5964C-1.98393 42.7381 8.44993 60.1016 25.5892 64.3756C42.7359 68.6506 60.1007 58.2178 64.3751 41.0751C68.6495 23.9311 58.2162 6.56514 41.0708 2.29124Z" fill="url(#paint4_linear_14800_609868)"/>
9
- <path d="M48.0289 30.1837C48.6924 25.7482 45.3154 23.3639 40.6977 21.7732L42.1956 15.7649L38.5383 14.8535L37.0799 20.7035C36.1185 20.4639 35.131 20.2378 34.1497 20.0139L35.6185 14.1253L31.9633 13.2139L30.4643 19.2201C29.6685 19.0389 28.8872 18.8597 28.1289 18.6712L28.1331 18.6524L23.0893 17.393L22.1164 21.2993C22.1164 21.2993 24.8299 21.9212 24.7727 21.9597C26.2539 22.3295 26.5216 23.3097 26.4768 24.0868L24.7706 30.9316C24.8727 30.9576 25.0049 30.9951 25.1508 31.0534C25.0289 31.0232 24.8987 30.9899 24.7643 30.9576L22.3727 40.5462C22.1914 40.9962 21.732 41.6712 20.6966 41.4149C20.7331 41.468 18.0383 40.7514 18.0383 40.7514L16.2227 44.9378L20.982 46.1243C21.8674 46.3462 22.7352 46.5784 23.5893 46.7972L22.0758 52.8743L25.7289 53.7857L27.2279 47.7732C28.2258 48.0441 29.1945 48.2941 30.1424 48.5295L28.6487 54.5139L32.306 55.4253L33.8195 49.3597C40.056 50.5399 44.7456 50.0639 46.7195 44.4232C48.3102 39.8816 46.6404 37.2618 43.3591 35.5534C45.7487 35.0024 47.5487 33.4305 48.0289 30.1837ZM39.6727 41.9014C38.5424 46.443 30.8956 43.9878 28.4164 43.3722L30.4247 35.3212C32.9039 35.9399 40.8539 37.1649 39.6727 41.9014ZM40.8039 30.118C39.7727 34.2493 33.4081 32.1503 31.3435 31.6357L33.1643 24.3337C35.2289 24.8482 41.8779 25.8087 40.8039 30.118Z" fill="url(#paint5_linear_14800_609868)"/>
10
- <path d="M48.0289 28.5836C48.6924 24.1481 45.3154 21.7638 40.6977 20.1731L42.1956 14.1648L38.5383 13.2534L37.0799 19.1034C36.1185 18.8638 35.131 18.6377 34.1497 18.4138L35.6185 12.5252L31.9633 11.6138L30.4643 17.62C29.6685 17.4388 28.8872 17.2596 28.1289 17.0711L28.1331 17.0523L23.0893 15.7929L22.1164 19.6992C22.1164 19.6992 24.8299 20.3211 24.7727 20.3596C26.2539 20.7294 26.5216 21.7096 26.4768 22.4867L24.7706 29.3315C24.8727 29.3575 25.0049 29.395 25.1508 29.4534C25.0289 29.4231 24.8987 29.3898 24.7643 29.3575L22.3727 38.9461C22.1914 39.3961 21.732 40.0711 20.6966 39.8148C20.7331 39.8679 18.0383 39.1513 18.0383 39.1513L16.2227 43.3377L20.982 44.5242C21.8674 44.7461 22.7352 44.9784 23.5893 45.1971L22.0758 51.2742L25.7289 52.1856L27.2279 46.1731C28.2258 46.444 29.1945 46.694 30.1424 46.9294L28.6487 52.9138L32.306 53.8252L33.8195 47.7596C40.056 48.9398 44.7456 48.4638 46.7195 42.8231C48.3102 38.2815 46.6404 35.6617 43.3591 33.9534C45.7487 33.4023 47.5487 31.8304 48.0289 28.5836ZM39.6727 40.3013C38.5424 44.8429 30.8956 42.3877 28.4164 41.7721L30.4247 33.7211C32.9039 34.3398 40.8539 35.5648 39.6727 40.3013ZM40.8039 28.5179C39.7727 32.6492 33.4081 30.5502 31.3435 30.0356L33.1643 22.7336C35.2289 23.2481 41.8779 24.2086 40.8039 28.5179Z" fill="white"/>
11
- <path d="M48.0289 28.5836C48.6924 24.1481 45.3154 21.7638 40.6977 20.1731L42.1956 14.1648L38.5383 13.2534L37.0799 19.1034C36.1185 18.8638 35.131 18.6377 34.1497 18.4138L35.6185 12.5252L31.9633 11.6138L30.4643 17.62C29.6685 17.4388 28.8872 17.2596 28.1289 17.0711L28.1331 17.0523L23.0893 15.7929L22.1164 19.6992C22.1164 19.6992 24.8299 20.3211 24.7727 20.3596C26.2539 20.7294 26.5216 21.7096 26.4768 22.4867L24.7706 29.3315C24.8727 29.3575 25.0049 29.395 25.1508 29.4534C25.0289 29.4231 24.8987 29.3898 24.7643 29.3575L22.3727 38.9461C22.1914 39.3961 21.732 40.0711 20.6966 39.8148C20.7331 39.8679 18.0383 39.1513 18.0383 39.1513L16.2227 43.3377L20.982 44.5242C21.8674 44.7461 22.7352 44.9784 23.5893 45.1971L22.0758 51.2742L25.7289 52.1856L27.2279 46.1731C28.2258 46.444 29.1945 46.694 30.1424 46.9294L28.6487 52.9138L32.306 53.8252L33.8195 47.7596C40.056 48.9398 44.7456 48.4638 46.7195 42.8231C48.3102 38.2815 46.6404 35.6617 43.3591 33.9534C45.7487 33.4023 47.5487 31.8304 48.0289 28.5836ZM39.6727 40.3013C38.5424 44.8429 30.8956 42.3877 28.4164 41.7721L30.4247 33.7211C32.9039 34.3398 40.8539 35.5648 39.6727 40.3013ZM40.8039 28.5179C39.7727 32.6492 33.4081 30.5502 31.3435 30.0356L33.1643 22.7336C35.2289 23.2481 41.8779 24.2086 40.8039 28.5179Z" fill="url(#paint6_linear_14800_609868)"/>
12
- <path d="M48.0289 28.5836C48.6924 24.1481 45.3154 21.7638 40.6977 20.1731L42.1956 14.1648L38.5383 13.2534L37.0799 19.1034C36.1185 18.8638 35.131 18.6377 34.1497 18.4138L35.6185 12.5252L31.9633 11.6138L30.4643 17.62C29.6685 17.4388 28.8872 17.2596 28.1289 17.0711L28.1331 17.0523L23.0893 15.7929L22.1164 19.6992C22.1164 19.6992 24.8299 20.3211 24.7727 20.3596C26.2539 20.7294 26.5216 21.7096 26.4768 22.4867L24.7706 29.3315C24.8727 29.3575 25.0049 29.395 25.1508 29.4534C25.0289 29.4231 24.8987 29.3898 24.7643 29.3575L22.3727 38.9461C22.1914 39.3961 21.732 40.0711 20.6966 39.8148C20.7331 39.8679 18.0383 39.1513 18.0383 39.1513L16.2227 43.3377L20.982 44.5242C21.8674 44.7461 22.7352 44.9784 23.5893 45.1971L22.0758 51.2742L25.7289 52.1856L27.2279 46.1731C28.2258 46.444 29.1945 46.694 30.1424 46.9294L28.6487 52.9138L32.306 53.8252L33.8195 47.7596C40.056 48.9398 44.7456 48.4638 46.7195 42.8231C48.3102 38.2815 46.6404 35.6617 43.3591 33.9534C45.7487 33.4023 47.5487 31.8304 48.0289 28.5836ZM39.6727 40.3013C38.5424 44.8429 30.8956 42.3877 28.4164 41.7721L30.4247 33.7211C32.9039 34.3398 40.8539 35.5648 39.6727 40.3013ZM40.8039 28.5179C39.7727 32.6492 33.4081 30.5502 31.3435 30.0356L33.1643 22.7336C35.2289 23.2481 41.8779 24.2086 40.8039 28.5179Z" fill="url(#paint7_linear_14800_609868)"/>
13
- <path d="M35.6185 12.5252L34.1497 18.4138C34.8857 18.5817 35.6251 18.7509 36.3544 18.926L37.0799 19.1034L38.5383 13.2534L42.1956 14.1648L40.6977 20.1731C45.3154 21.7638 48.6924 24.1481 48.0289 28.5836C47.5487 31.8304 45.7487 33.4023 43.3591 33.9534C46.6404 35.6617 48.3102 38.2815 46.7195 42.8231C44.7456 48.4638 40.056 48.9398 33.8195 47.7596L32.306 53.8252L28.6487 52.9138L30.1424 46.9294C29.1945 46.694 28.2258 46.444 27.2279 46.1731L25.7289 52.1856L22.0758 51.2742L23.5893 45.1971C22.7352 44.9784 21.8674 44.7461 20.982 44.5242L16.2227 43.3377L18.0383 39.1513C18.0383 39.1513 20.7331 39.8679 20.6966 39.8148C21.732 40.0711 22.1914 39.3961 22.3727 38.9461L24.7643 29.3575C24.8987 29.3898 25.0289 29.4231 25.1508 29.4534C25.0049 29.395 24.8727 29.3575 24.7706 29.3315L26.4768 22.4867C26.5216 21.7096 26.2539 20.7294 24.7727 20.3596C24.8299 20.3211 22.1184 19.6996 22.1164 19.6992L23.0893 15.7929L28.1331 17.0523L28.1289 17.0711C28.5081 17.1653 28.893 17.2574 29.2826 17.3484L30.4643 17.62L31.9633 11.6138L35.6185 12.5252ZM30.8552 18.256L30.3458 18.1401C29.5502 17.9589 28.7643 17.7785 28.0003 17.5885L27.4953 17.4632L27.4995 17.4437L23.4776 16.4396L22.7646 19.3021C23.0032 19.3576 23.2971 19.4264 23.5898 19.4963C23.9261 19.5766 24.264 19.6589 24.5154 19.7239C24.6397 19.7561 24.7494 19.7857 24.8286 19.8096C24.8651 19.8206 24.9101 19.8347 24.9497 19.8505C24.954 19.8522 24.9643 19.8564 24.9784 19.8627C25.7828 20.0791 26.3243 20.4754 26.6474 20.9846C26.9735 21.4985 27.0357 22.061 27.0094 22.5174L27.0065 22.5672L26.9943 22.6156L25.288 29.4604L25.1943 29.4369L25.1862 29.4627L25.2818 29.4867L22.8901 39.0752L22.8812 39.1109L22.8674 39.1453C22.7572 39.419 22.5476 39.8027 22.1674 40.0776C21.7796 40.358 21.268 40.4848 20.6432 40.3489C20.6232 40.3474 20.6088 40.3457 20.6034 40.345C20.5651 40.34 20.5217 40.3315 20.4849 40.3239C20.4057 40.3076 20.2964 40.2821 20.1716 40.252C19.9199 40.1913 19.583 40.1059 19.2479 40.0195C18.9218 39.9354 18.595 39.8496 18.3451 39.7838L16.9622 42.9724L21.1109 44.0067H21.1117C21.9966 44.2285 22.8772 44.4642 23.7216 44.6804L24.2349 44.8119L22.7219 50.8856L25.3404 51.539L26.8422 45.5159L27.3674 45.6586C28.3612 45.9283 29.3264 46.1771 30.2711 46.4117L30.7893 46.5406L29.2953 52.5252L31.9174 53.1786L33.424 47.1419L33.9187 47.2356C37.0189 47.8223 39.6425 47.9761 41.7112 47.3396C43.7316 46.7178 45.2792 45.3243 46.2161 42.6471C46.9818 40.4608 46.9366 38.8163 46.3776 37.5395C45.8155 36.2558 44.693 35.2493 43.1128 34.4265L41.8302 33.7586L43.2393 33.4336C44.3532 33.1767 45.2981 32.6901 46.0198 31.9159C46.741 31.142 47.2738 30.0439 47.5013 28.5054L47.5016 28.5047C47.8072 26.4614 47.1908 24.9228 45.9651 23.6872C44.7129 22.4249 42.8067 21.4636 40.524 20.6773L40.062 20.5182L41.549 14.5531L38.9266 13.8997L37.4685 19.7497L36.951 19.6208C35.9955 19.3827 35.0128 19.1579 34.031 18.9338L33.5005 18.8127L34.9719 12.9135L32.3516 12.2601L30.8552 18.256ZM30.5539 33.2036C31.7395 33.4995 34.4332 33.9792 36.6417 34.9815C37.7505 35.4847 38.8004 36.1452 39.4948 37.0336C40.2086 37.9469 40.5272 39.0789 40.1901 40.4304C39.8638 41.7411 39.0508 42.5639 37.999 43.0226C36.9747 43.4693 35.7396 43.5667 34.5227 43.5034C32.0931 43.3768 29.4876 42.5878 28.2878 42.2898L27.7698 42.1612L30.0365 33.0744L30.5539 33.2036ZM28.4164 41.7721C30.8956 42.3877 38.5424 44.8429 39.6727 40.3013C40.8539 35.5648 32.9039 34.3398 30.4247 33.7211L28.4164 41.7721ZM33.2932 22.2161C34.2662 22.4586 36.5394 22.8473 38.3888 23.7203C39.3203 24.16 40.2074 24.7487 40.7872 25.5578C41.3838 26.3903 41.6272 27.4193 41.3214 28.6468C41.0242 29.8374 40.3257 30.6069 39.4141 31.05C38.5281 31.4805 37.4712 31.5899 36.4417 31.552C34.3912 31.4767 32.2032 30.7995 31.2146 30.5531L30.6969 30.4242L32.7758 22.0872L33.2932 22.2161ZM31.3435 30.0356C33.4081 30.5502 39.7727 32.6492 40.8039 28.5179C41.8779 24.2086 35.2289 23.2481 33.1643 22.7336L31.3435 30.0356Z" fill="url(#paint8_linear_14800_609868)"/>
14
- </g>
15
- <path d="M96.2235 71.9527C91.7714 89.81 73.6849 100.678 55.8255 96.2245C37.9735 91.7725 27.1058 73.685 31.5599 55.8287C36.0099 37.9693 54.0964 27.1006 71.9505 31.5527C89.8089 36.0048 100.676 54.0943 96.2235 71.9527Z" fill="#F7931A"/>
16
- <path d="M96.2235 71.9527C91.7714 89.81 73.6849 100.678 55.8255 96.2245C37.9735 91.7725 27.1058 73.685 31.5599 55.8287C36.0099 37.9693 54.0964 27.1006 71.9505 31.5527C89.8089 36.0048 100.676 54.0943 96.2235 71.9527Z" fill="url(#paint9_linear_14800_609868)"/>
17
- <path d="M96.2235 71.9527C91.7714 89.81 73.6849 100.678 55.8255 96.2245C37.9735 91.7725 27.1058 73.685 31.5599 55.8287C36.0099 37.9693 54.0964 27.1006 71.9505 31.5527C89.8089 36.0048 100.676 54.0943 96.2235 71.9527Z" fill="url(#paint10_linear_14800_609868)"/>
18
- <path d="M96.2235 71.9527C91.7714 89.81 73.6849 100.678 55.8255 96.2245C37.9735 91.7725 27.1058 73.685 31.5599 55.8287C36.0099 37.9693 54.0964 27.1006 71.9505 31.5527C89.8089 36.0048 100.676 54.0943 96.2235 71.9527Z" fill="url(#paint11_linear_14800_609868)"/>
19
- <path d="M31.5599 55.8287C36.01 37.9694 54.0964 27.1006 71.9506 31.5527C89.8089 36.0047 100.676 54.0944 96.2235 71.9526L96.1167 72.3701C91.5253 89.8403 73.827 100.475 56.244 96.3261L55.8256 96.2245C37.9735 91.7724 27.1058 73.6849 31.5599 55.8287ZM71.6279 32.8464C54.4885 28.5726 37.1257 39.0063 32.8537 56.1511V56.1516C28.5778 73.2933 39.0106 90.6568 56.148 94.9308C73.2928 99.2057 90.6558 88.7729 94.9297 71.6303C99.2037 54.4862 88.7715 37.1203 71.6279 32.8464Z" fill="url(#paint12_linear_14800_609868)"/>
20
- <path d="M31.5599 55.8287C36.01 37.9694 54.0964 27.1006 71.9506 31.5527C89.8089 36.0047 100.676 54.0944 96.2235 71.9526L96.1167 72.3701C91.5253 89.8403 73.827 100.475 56.244 96.3261L55.8256 96.2245C37.9735 91.7724 27.1058 73.6849 31.5599 55.8287ZM71.6279 32.8464C54.4885 28.5726 37.1257 39.0063 32.8537 56.1511V56.1516C28.5778 73.2933 39.0106 90.6568 56.148 94.9308C73.2928 99.2057 90.6558 88.7729 94.9297 71.6303C99.2037 54.4862 88.7715 37.1203 71.6279 32.8464Z" fill="url(#paint13_linear_14800_609868)"/>
21
- <path d="M31.5599 55.8287C36.01 37.9694 54.0964 27.1006 71.9506 31.5527C89.8089 36.0047 100.676 54.0944 96.2235 71.9526L96.1167 72.3701C91.5253 89.8403 73.827 100.475 56.244 96.3261L55.8256 96.2245C37.9735 91.7724 27.1058 73.6849 31.5599 55.8287ZM71.6279 32.8464C54.4885 28.5726 37.1257 39.0063 32.8537 56.1511V56.1516C28.5778 73.2933 39.0106 90.6568 56.148 94.9308C73.2928 99.2057 90.6558 88.7729 94.9297 71.6303C99.2037 54.4862 88.7715 37.1203 71.6279 32.8464Z" fill="url(#paint14_linear_14800_609868)"/>
22
- <path d="M46.5206 67.6513L71.4546 46.1656C72.5411 45.4698 73.5767 46.1656 72.9135 47.3592L64.9559 63.0094H79.147C79.147 63.0094 81.4017 63.0094 79.147 64.8662L54.6109 86.4844C52.8868 87.9434 51.6931 87.1476 52.8868 84.8929L60.5792 69.6408H46.5206C46.5206 69.6408 44.266 69.6408 46.5206 67.6513Z" fill="url(#paint15_linear_14800_609868)"/>
23
- <path d="M46.5206 64.9843L71.4546 43.4986C72.5411 42.8028 73.5767 43.4986 72.9135 44.6922L64.9559 60.3424H79.147C79.147 60.3424 81.4017 60.3424 79.147 62.1992L54.6109 83.8175C52.8868 85.2764 51.6931 84.4806 52.8868 82.2259L60.5792 66.9738H46.5206C46.5206 66.9738 44.266 66.9738 46.5206 64.9843Z" fill="url(#paint16_linear_14800_609868)"/>
24
- <path d="M71.4547 43.4985C72.5412 42.8028 73.5767 43.4987 72.9136 44.6922L64.9558 60.3425H79.1469C79.1469 60.3425 81.4016 60.3425 79.1469 62.1993L54.611 83.8175L54.5305 83.8842C52.8501 85.2511 51.7118 84.4453 52.8868 82.2258L60.5792 66.9738H46.5206L46.4282 66.9699C46.0347 66.9431 44.6002 66.7328 46.4183 65.0761L46.5206 64.9844L71.4547 43.4985ZM72.5183 43.812C72.4487 43.7593 72.185 43.6755 71.7693 43.931L46.8688 65.3883C46.3257 65.8682 46.1264 66.1691 46.0683 66.323C46.065 66.3316 46.0628 66.3394 46.0607 66.3462C46.1043 66.369 46.1825 66.3974 46.2962 66.4175C46.3611 66.429 46.4211 66.4349 46.4644 66.4378C46.4856 66.4393 46.502 66.4399 46.512 66.4402C46.517 66.4403 46.5204 66.4404 46.5219 66.4404H61.4454L53.3631 82.4662L53.3605 82.4709L53.3581 82.4756C53.0793 83.0022 52.963 83.4021 52.9417 83.6727C52.9312 83.8059 52.945 83.8923 52.961 83.9422C52.9759 83.9887 52.9913 84.0006 52.9925 84.0016C52.9944 84.0032 53.0085 84.0146 53.0527 84.0196C53.1015 84.0251 53.1828 84.0218 53.3006 83.9883C53.5397 83.9204 53.8712 83.7446 54.2665 83.4102L78.7943 61.799L78.8011 61.793L78.8079 61.7876C79.3195 61.3662 79.5217 61.0955 79.5902 60.9537C79.5427 60.9347 79.4718 60.9133 79.3774 60.8977C79.311 60.8868 79.25 60.881 79.2058 60.8782C79.184 60.8768 79.167 60.8761 79.1566 60.8758H64.0863L72.4381 44.4506L72.4425 44.4417L72.4472 44.4331C72.5755 44.2022 72.5953 44.0424 72.587 43.954C72.5796 43.8743 72.5499 43.836 72.5183 43.812Z" fill="white"/>
25
- </g>
26
- <defs>
27
- <linearGradient id="paint0_linear_14800_609868" x1="33.3333" y1="0" x2="33.3333" y2="66.6673" gradientUnits="userSpaceOnUse">
28
- <stop stop-color="#F7BC1A"/>
29
- <stop offset="1" stop-color="#FF6A00"/>
30
- </linearGradient>
31
- <linearGradient id="paint1_linear_14800_609868" x1="33.3333" y1="0" x2="33.3333" y2="66.6673" gradientUnits="userSpaceOnUse">
32
- <stop offset="0.725084" stop-color="#C94701" stop-opacity="0"/>
33
- <stop offset="1" stop-color="#C94701" stop-opacity="0.3"/>
34
- </linearGradient>
35
- <linearGradient id="paint2_linear_14800_609868" x1="33.3333" y1="9.32637e-05" x2="33.3333" y2="66.6674" gradientUnits="userSpaceOnUse">
36
- <stop stop-color="#FFE091"/>
37
- <stop offset="1" stop-color="#FF9735"/>
38
- </linearGradient>
39
- <linearGradient id="paint3_linear_14800_609868" x1="33.3333" y1="9.32637e-05" x2="33.3333" y2="66.6674" gradientUnits="userSpaceOnUse">
40
- <stop offset="0.85" stop-color="#FFA54D" stop-opacity="0"/>
41
- <stop offset="1" stop-color="#FFA54D"/>
42
- </linearGradient>
43
- <linearGradient id="paint4_linear_14800_609868" x1="33.3333" y1="9.32637e-05" x2="33.3333" y2="66.6674" gradientUnits="userSpaceOnUse">
44
- <stop stop-color="#FFF3DA"/>
45
- <stop offset="0.15" stop-color="#FFF3DA" stop-opacity="0"/>
46
- </linearGradient>
47
- <linearGradient id="paint5_linear_14800_609868" x1="32.1674" y1="13.2139" x2="32.1674" y2="55.4253" gradientUnits="userSpaceOnUse">
48
- <stop stop-color="#F89A02"/>
49
- <stop offset="1" stop-color="#F56600"/>
50
- </linearGradient>
51
- <linearGradient id="paint6_linear_14800_609868" x1="32.1675" y1="11.6138" x2="32.1675" y2="53.8252" gradientUnits="userSpaceOnUse">
52
- <stop stop-color="white"/>
53
- <stop offset="1" stop-color="#FFF1CF"/>
54
- </linearGradient>
55
- <linearGradient id="paint7_linear_14800_609868" x1="32.1675" y1="11.6138" x2="32.1675" y2="53.8252" gradientUnits="userSpaceOnUse">
56
- <stop stop-color="white"/>
57
- <stop offset="1" stop-color="#FEEABD"/>
58
- </linearGradient>
59
- <linearGradient id="paint8_linear_14800_609868" x1="32.1675" y1="11.6138" x2="32.1675" y2="53.8252" gradientUnits="userSpaceOnUse">
60
- <stop stop-color="white"/>
61
- <stop offset="1" stop-color="white"/>
62
- </linearGradient>
63
- <linearGradient id="paint9_linear_14800_609868" x1="63.8913" y1="30.5552" x2="63.8913" y2="97.2225" gradientUnits="userSpaceOnUse">
64
- <stop stop-color="#F7BC1A"/>
65
- <stop offset="1" stop-color="#FF7700"/>
66
- </linearGradient>
67
- <linearGradient id="paint10_linear_14800_609868" x1="63.8913" y1="30.5552" x2="63.8913" y2="97.2225" gradientUnits="userSpaceOnUse">
68
- <stop stop-color="#F7BC1A"/>
69
- <stop offset="1" stop-color="#FF6A00"/>
70
- </linearGradient>
71
- <linearGradient id="paint11_linear_14800_609868" x1="63.8913" y1="30.5552" x2="63.8913" y2="97.2225" gradientUnits="userSpaceOnUse">
72
- <stop offset="0.725084" stop-color="#C94701" stop-opacity="0"/>
73
- <stop offset="1" stop-color="#C94701" stop-opacity="0.3"/>
74
- </linearGradient>
75
- <linearGradient id="paint12_linear_14800_609868" x1="63.8913" y1="30.5553" x2="63.8913" y2="97.2226" gradientUnits="userSpaceOnUse">
76
- <stop stop-color="#FFE091"/>
77
- <stop offset="1" stop-color="#FF9735"/>
78
- </linearGradient>
79
- <linearGradient id="paint13_linear_14800_609868" x1="63.8913" y1="30.5553" x2="63.8913" y2="97.2226" gradientUnits="userSpaceOnUse">
80
- <stop offset="0.85" stop-color="#FFA54D" stop-opacity="0"/>
81
- <stop offset="1" stop-color="#FFA54D"/>
82
- </linearGradient>
83
- <linearGradient id="paint14_linear_14800_609868" x1="63.8913" y1="30.5553" x2="63.8913" y2="97.2226" gradientUnits="userSpaceOnUse">
84
- <stop stop-color="#FFF3DA"/>
85
- <stop offset="0.15" stop-color="#FFF3DA" stop-opacity="0"/>
86
- </linearGradient>
87
- <linearGradient id="paint15_linear_14800_609868" x1="62.8338" y1="45.8887" x2="62.8338" y2="87.222" gradientUnits="userSpaceOnUse">
88
- <stop stop-color="#F89A02"/>
89
- <stop offset="1" stop-color="#F56600"/>
90
- </linearGradient>
91
- <linearGradient id="paint16_linear_14800_609868" x1="62.8338" y1="43.2217" x2="62.8338" y2="84.555" gradientUnits="userSpaceOnUse">
92
- <stop stop-color="white"/>
93
- <stop offset="1" stop-color="#FEEABD"/>
94
- </linearGradient>
95
- <clipPath id="clip0_14800_609868">
96
- <rect width="100" height="100" fill="white"/>
97
- </clipPath>
98
- </defs>
99
-</svg>
assets/litecoin_electrum_server_list.yml
+7
@@ -2,20 +2,27 @@
2
uri: ltc-electrum.cakewallet.com:50002
3
useSSL: true
4
isDefault: true
5
+ isOfficial: true
6
isEnabledForAutoSwitching: true
7
+ label: "Cake Wallet"
8
-
9
uri: litecoin.stackwallet.com:20063
10
useSSL: true
11
isEnabledForAutoSwitching: true
12
+ label: "Stack Wallet"
13
-
14
uri: electrum-ltc.bysh.me:50002
15
useSSL: true
16
+ label: "Bysh"
17
-
18
uri: lightweight.fiatfaucet.com:50002
19
useSSL: true
20
+ label: "Fiat Faucet"
21
-
22
uri: electrum.ltc.xurious.com:50002
23
useSSL: true
24
+ label: "Xurious"
25
-
26
uri: backup.electrum-ltc.org:443
27
useSSL: true
28
+ label: "Electrum-LTC"
assets/nano_node_list.yml
+10
-7
@@ -1,34 +1,37 @@
1
-
2
- uri: nano.nownodes.io
2
+ uri: rpc.nano.to
3
+ isDefault: true
4
useSSL: true
5
isEnabledForAutoSwitching: true
6
+ label: "Nano.to"
7
-
6
- uri: rpc.nano.to
7
- is_default: true
8
+ uri: nano.nownodes.io
9
useSSL: true
10
isEnabledForAutoSwitching: true
11
+ label: "NOWNodes"
12
-
13
uri: node.nautilus.io
14
path: /api
15
useSSL: true
16
isEnabledForAutoSwitching: true
17
+ label: "Nautilus"
18
-
19
uri: app.natrium.io
20
path: /api
21
useSSL: true
22
+ label: "Natrium"
23
-
24
uri: rainstorm.city
25
path: /api
26
useSSL: true
27
+ label: "Rainstorm City"
28
-
29
uri: node.somenano.com
30
path: /proxy
31
useSSL: true
32
+ label: "SomeNano"
33
-
34
uri: nanoslo.0x.no
35
path: /proxy
36
useSSL: true
31
--
32
- uri: www.bitrequest.app
33
- port: 8020
34
- useSSL: true
\ No newline at end of file
37
+ label: "0x.no"
\ No newline at end of file
assets/node_list.yml
+10
-8
@@ -1,34 +1,36 @@
1
-
2
+ label: "Cake Wallet"
3
uri: xmr-node.cakewallet.com:18081
3
- is_default: true
4
+ isDefault: true
5
+ isOfficial: true
6
trusted: true
7
useSSL: true
8
isEnabledForAutoSwitching: true
9
-
10
+ label: "Cake Wallet (Onion)"
11
uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081
9
- is_default: false
12
-
13
+ label: "Seth For Privacy"
14
uri: node.sethforprivacy.com:443
15
useSSL: true
13
- is_default: false
16
isEnabledForAutoSwitching: true
17
-
18
+ label: "MoneroDevs"
19
uri: node.monerodevs.org:18089
20
useSSL: true
18
- is_default: false
21
-
22
+ label: "MoneroDevs #2"
23
uri: node2.monerodevs.org:18089
24
useSSL: true
22
- is_default: false
25
-
26
+ label: "MoneroDevs #3"
27
uri: node3.monerodevs.org:18089
28
useSSL: true
26
- is_default: false
29
-
30
+ label: "Feather Wallet"
31
uri: selsta1.featherwallet.net:18081
32
useSSL: true
30
- is_default: false
33
-
34
+ label: "StormyCloud"
35
uri: xmr.stormycloud.org:18089
36
useSSL: true
34
- is_default: false
assets/polygon_node_list.yml
+5
-5
@@ -1,14 +1,14 @@
1
--
2
- uri: polygon-rpc.com
1
-
2
uri: polygon-bor-rpc.publicnode.com
3
useSSL: true
4
isDefault: true
5
isEnabledForAutoSwitching: true
6
+ label: "polygon-bor-rpc.publicnode.com"
7
-
9
- uri: polygon.llamarpc.com
10
- useSSL: true
8
+ uri: polygon-rpc.com
9
+ label: "Ankr"
10
-
11
uri: matic.nownodes.io
12
useSSL: true
14
- isEnabledForAutoSwitching: true
\ No newline at end of file
13
+ isEnabledForAutoSwitching: true
14
+ label: "NOWNodes"
\ No newline at end of file
assets/solana_node_list.yml
+9
-5
@@ -1,16 +1,20 @@
1
+-
2
+ uri: solana-mainnet.core.chainstack.com
3
+ useSSL: true
4
+ isDefault: true
5
+ isEnabledForAutoSwitching: true
6
+ label: "Chainstack"
7
-
8
uri: rpc.ankr.com
9
useSSL: true
10
+ label: "Ankr"
11
-
12
uri: api.mainnet-beta.solana.com:443
13
useSSL: true
14
isEnabledForAutoSwitching: true
15
+ label: "Solana Beta"
16
-
17
uri: solana-rpc.publicnode.com:443
18
useSSL: true
19
isEnabledForAutoSwitching: true
12
--
13
- uri: solana-mainnet.core.chainstack.com
14
- useSSL: true
15
- is_default: true
16
- isEnabledForAutoSwitching: true
\ No newline at end of file
20
+ label: "PublicNode"
\ No newline at end of file
assets/tron_node_list.yml
+8
-6
@@ -1,13 +1,15 @@
1
--
2
- uri: tron-rpc.publicnode.com:443
3
- is_default: false
4
- useSSL: true
1
-
2
uri: api.trongrid.io
7
- is_default: true
3
+ isDefault: true
4
useSSL: true
5
isEnabledForAutoSwitching: true
6
+ label: "TronGrid"
7
+-
8
+ uri: tron-rpc.publicnode.com:443
9
+ useSSL: true
10
+ label: "PublicNode"
11
-
12
uri: trx.nownodes.io
13
useSSL: true
13
- isEnabledForAutoSwitching: true
\ No newline at end of file
14
+ isEnabledForAutoSwitching: true
15
+ label: "NOWNodes"
\ No newline at end of file
assets/wownero_node_list.yml
+1
-3
@@ -1,14 +1,12 @@
1
-
2
uri: node3.monerodevs.org:34568
3
- is_default: true
3
+ isDefault: true
4
useSSL: false
5
isEnabledForAutoSwitching: true
6
-
7
uri: node2.monerodevs.org:34568
8
- is_default: false
8
useSSL: false
9
isEnabledForAutoSwitching: true
10
-
11
uri: node.monerodevs.org:34568
13
- is_default: false
12
useSSL: false
assets/zano_node_list.yml
+5
-2
@@ -1,9 +1,12 @@
1
-
2
uri: 37.27.100.59:10500
3
- is_default: true
3
+ isDefault: true
4
useSSL: false
5
isEnabledForAutoSwitching: true
6
+ label: "Zano"
7
-
8
uri: zano.cakewallet.com:11211
9
useSSL: false
9
- isEnabledForAutoSwitching: true
\ No newline at end of file
10
+ isOfficial: true
11
+ isEnabledForAutoSwitching: true
12
+ label: "Cake Wallet"
assets/zcash_node_list.yml
+14
-6
@@ -1,12 +1,20 @@
1
-- uri: zec.rocks:443
2
- is_default: false
1
+-
2
+ uri: zec-node.cakewallet.com:443
3
+ isDefault: true
4
+ isOfficial: true
5
useSSL: true
6
isEnabledForAutoSwitching: true
5
-- uri: zec-node.cakewallet.com:443
6
- is_default: true
7
+ label: "Cake Wallet"
8
+-
9
+ uri: zec.rocks:443
10
useSSL: true
11
isEnabledForAutoSwitching: true
9
-- uri: 2c4whzg26j6hgjh22rxynj3oig4gm22ga7x74weclujywxye23v3u5id.onion:9067
12
+ label: "Zec.rocks"
13
+-
14
+ uri: 2c4whzg26j6hgjh22rxynj3oig4gm22ga7x74weclujywxye23v3u5id.onion:9067
15
useSSL: false
11
-- uri: bvp2l442g5ogma7rywzahm7eqyhpp3g26n3gvvxeioqn5csio2ir6myd.onion:9067
16
+ label: "Cake Wallet (Tor)"
17
+-
18
+ uri: bvp2l442g5ogma7rywzahm7eqyhpp3g26n3gvvxeioqn5csio2ir6myd.onion:9067
19
useSSL: false
20
+ label: "Cake Wallet (Tor #2)"
\ No newline at end of file
cw_bitcoin/lib/electrum_wallet.dart
+3
-2
@@ -790,9 +790,10 @@ abstract class ElectrumWalletBase
790
791
if (server.toLowerCase().contains('electrs')) {
792
node!.isElectrs = true;
793
- if (node!.isInBox) {
793
+ // TODO figure out why condition was needed
794
+ // if (node!.isInBox) {
795
node!.save();
795
- }
796
+ // }
797
return node!.isElectrs!;
798
}
799
}
cw_core/lib/db/sqlite.dart
+27
-1
@@ -41,7 +41,7 @@ Future<void> initDb({String? pathOverride}) async {
41
}
42
}
43
await db?.close();
44
- db = await openDatabase(dbFile.path, version: 7,
44
+ db = await openDatabase(dbFile.path, version: 8,
45
onUpgrade: (Database db, int oldVersion, int newVersion) async {
46
printV("migrating: $oldVersion, $newVersion");
47
if (oldVersion <= 1) {
@@ -104,6 +104,9 @@ CREATE TABLE IF NOT EXISTS BalanceCardStyleSettings (
104
definition: 'TEXT',
105
);
106
}
107
+ if(oldVersion <= 7) {
108
+ await _createNodeTable(db);
109
+ }
110
},
111
onCreate: (Database db, int version) async {
112
await db.execute(
@@ -202,6 +205,7 @@ CREATE TABLE BalanceCardStyleSettings (
205
);
206
''');
207
await _createBridgeTransferTable(db);
208
+ await _createNodeTable(db);
209
await _createTradeTable(db);
210
}
211
);
@@ -330,4 +334,26 @@ CREATE TABLE IF NOT EXISTS BridgeTransfer (
334
CREATE INDEX IF NOT EXISTS idx_bridgetransfer_wallet_id
335
ON BridgeTransfer(wallet_id);
336
''');
337
+}
338
+
339
+Future<void> _createNodeTable(Database db) async {
340
+ db.execute("""
341
+CREATE TABLE Node (
342
+NodeId INTEGER PRIMARY KEY,
343
+uri TEXT NOT NULL,
344
+path TEXT,
345
+login TEXT,
346
+label TEXT,
347
+password TEXT,
348
+isPow INTEGER NOT NULL,
349
+useSSL INTEGER,
350
+typeRaw INTEGER NOT NULL,
351
+trusted INTEGER NOT NULL,
352
+socksProxyAddress TEXT,
353
+isEnabledForAutoSwitching BOOLEAN DEFAULT FALSE,
354
+isOfficial BOOLEAN DEFAULT FALSE,
355
+isBuiltin BOOLEAN DEFAULT FALSE,
356
+isDefault BOOLEAN DEFAULT FALSE
357
+);
358
+ """);
359
}
\ No newline at end of file
cw_core/lib/node.dart
+154
-50
@@ -1,33 +1,62 @@
1
+import 'dart:convert';
2
import 'dart:io';
2
-import 'package:cw_core/keyable.dart';
3
+import 'dart:math' as math;
4
+
5
+import 'package:blockchain_utils/hex/hex.dart';
6
+import 'package:cw_core/node_list.dart';
7
+import 'package:cw_core/utils/print_verbose.dart';
8
import 'package:cw_core/utils/proxy_socket/abstract.dart';
9
import 'package:cw_core/utils/proxy_wrapper.dart';
5
-import 'package:cw_core/utils/print_verbose.dart';
6
-import 'dart:convert';
7
-import 'package:hive/hive.dart';
8
-import 'package:cw_core/hive_type_ids.dart';
10
import 'package:cw_core/wallet_type.dart';
10
-import 'dart:math' as math;
11
-import 'package:convert/convert.dart';
12
-
11
import 'package:crypto/crypto.dart';
12
+import 'package:sqflite/sqflite.dart';
13
15
-part 'node.g.dart';
14
+import 'db/sqlite.dart';
15
16
Uri createUriFromElectrumAddress(String address, String path) =>
17
Uri.tryParse('tcp://$address$path')!;
18
20
-@HiveType(typeId: Node.typeId)
21
-class Node extends HiveObject with Keyable {
19
+Future<void> validateBuiltinNodes() async {
20
+ // ensures nodes stored as builtin in the db correspond to the nodes in the .yml files
21
+
22
+ final builtinFromDb = await Node.getAllBuiltin();
23
+ final builtinFromList = await loadAllDefaultNodes();
24
+
25
+ for (final listNode in builtinFromList) {
26
+ // preserve proxy settings from user
27
+ try {
28
+ final matchedDbNode = builtinFromDb.firstWhere(
29
+ (dbNode) => dbNode.uri == listNode.uri
30
+ );
31
+ listNode.socksProxyAddress = matchedDbNode.socksProxyAddress;
32
+ } catch(e) {}
33
+ }
34
+
35
+ final dbSet = builtinFromDb.toSet();
36
+ final listSet = builtinFromList.toSet();
37
+
38
+ final nodesToDelete = dbSet.difference(listSet);
39
+ final nodesToAdd = listSet.difference(dbSet);
40
+
41
+ for (final node in nodesToDelete) await node.delete();
42
+ for (final node in nodesToAdd) await node.save();
43
+}
44
+
45
+class Node {
46
Node({
47
+ this.id = 0,
48
this.label,
49
this.login,
50
this.password,
51
this.useSSL,
52
+ this.isPow = false,
53
this.trusted = false,
54
this.socksProxyAddress,
55
this.path = '',
56
this.isEnabledForAutoSwitching = false,
57
+ this.isOfficial = false,
58
+ this.isBuiltin = false,
59
+ this.isDefault = false,
60
String? uri,
61
WalletType? type,
62
}) {
@@ -50,62 +79,144 @@ class Node extends HiveObject with Keyable {
79
trusted: $trusted,
80
socksProxyAddress: $socksProxyAddress,
81
isEnabledForAutoSwitching: $isEnabledForAutoSwitching,
82
+ isOfficial: $isOfficial,
83
+ isBuiltin: $isBuiltin,
84
+ isDefault: $isDefault
85
})""";
86
}
87
88
Node.fromMap(Map<String, Object?> map)
57
- : uriRaw = map['uri'] as String? ?? '',
89
+ : id = (map[selfIdColumn] ?? 0) as int,
90
+ uriRaw = map['uri'] as String? ?? '',
91
path = map['path'] as String? ?? '',
92
login = map['login'] as String?,
93
label = map['label'] as String?,
94
password = map['password'] as String?,
62
- useSSL = map['useSSL'] as bool?,
63
- trusted = map['trusted'] as bool? ?? false,
64
- socksProxyAddress = map['socksProxyPort'] as String?,
65
- isEnabledForAutoSwitching = map['isEnabledForAutoSwitching'] as bool? ?? false;
95
+ isPow = (map["isPow"] != null && map['isPow'] != 0) as bool? ?? false,
96
+ useSSL = (map['useSSL'] != 0) as bool?,
97
+ typeRaw = (map["typeRaw"] ?? 0) as int,
98
+ trusted = (map['trusted'] != 0) as bool? ?? false,
99
+ socksProxyAddress = map['socksProxyAddress'] as String?,
100
+ isEnabledForAutoSwitching = (map['isEnabledForAutoSwitching'] != 0) as bool? ?? false,
101
+ isOfficial = (map['isOfficial'] != 0) as bool? ?? false,
102
+ isBuiltin = (map['isBuiltin'] != 0) as bool? ?? false,
103
+ isDefault = (map['isDefault'] != 0) as bool? ?? false;
104
+
105
+ Map<String, dynamic> toMap() {
106
+ return {
107
+ selfIdColumn: id,
108
+ 'uri': uriRaw,
109
+ 'path': path,
110
+ 'login': login,
111
+ "label": label,
112
+ 'password': password,
113
+ "isPow": isPow,
114
+ 'useSSL': useSSL,
115
+ "typeRaw": typeRaw,
116
+ 'trusted': trusted,
117
+ 'socksProxyAddress': socksProxyAddress,
118
+ 'isEnabledForAutoSwitching': isEnabledForAutoSwitching,
119
+ "isOfficial": isOfficial,
120
+ "isBuiltin": isBuiltin,
121
+ "isDefault": isDefault
122
+ };
123
+ }
124
67
- static const typeId = NODE_TYPE_ID;
68
- static const boxName = 'Nodes';
125
+ Future<int> delete() async {
126
+ return await db!.delete(tableName, where: '${selfIdColumn} = ?', whereArgs: [id]);
127
+ }
128
70
- @HiveField(0, defaultValue: '')
71
- late String uriRaw;
129
+ static Future<int> deleteAll() async {
130
+ return await db!.delete(tableName, where: "isPow = ?", whereArgs: [false]);
131
+ }
132
73
- @HiveField(1)
74
- String? login;
133
+ static Future<int> deleteAllPow() async {
134
+ return await db!.delete(tableName, where: "isPow = ?", whereArgs: [true]);
135
+ }
136
76
- @HiveField(2)
77
- String? password;
137
+ Future<int> save() async {
138
79
- @HiveField(3, defaultValue: 0)
80
- late int typeRaw;
139
+ final json = toMap();
140
+ if (json[selfIdColumn] == 0) {
141
+ json[selfIdColumn] = null;
142
+ }
143
+ id = await db!.insert(tableName, json, conflictAlgorithm: ConflictAlgorithm.replace);
144
+ return id;
145
+ }
146
82
- @HiveField(4)
83
- bool? useSSL;
147
85
- @HiveField(5, defaultValue: false)
86
- bool trusted;
148
+ static Future<List<Node>> selectList(String where, List<dynamic> whereArgs, {String? orderBy}) async {
149
+ if(orderBy == null) {
150
+ orderBy = selfIdColumn;
151
+ }
152
+ final list = await db!.query(
153
+ tableName,
154
+ where: where.isNotEmpty ? where : "1 = 1",
155
+ whereArgs: whereArgs.isNotEmpty ? whereArgs : null,
156
+ orderBy: orderBy,
157
+ );
158
+ printV("selectList: $list");
159
+ return List.generate(list.length, (index) => Node.fromMap(list[index]));
160
+ }
161
88
- @HiveField(6)
89
- String? socksProxyAddress;
162
91
- @HiveField(7, defaultValue: '')
92
- String? path;
163
+ static Future<List<Node>> getAll() async {
164
+ return selectList("isPow = ?", [false]);
165
+ }
166
94
- @HiveField(8)
95
- bool? isElectrs;
167
+ static Future<List<Node>> getAllBuiltin() async {
168
+ return selectList("isPow = ? AND isBuiltin = ?", [false, true]);
169
+ }
170
97
- @HiveField(9)
98
- bool? supportsSilentPayments;
171
+ static Future<List<Node>> getAllPowBuiltin() async {
172
+ return selectList("isPow = ? AND isBuiltin = ?", [true, true]);
173
+ }
174
100
- @HiveField(10)
101
- bool? supportsMweb;
175
+ static Future<List<Node>> getAllForWalletType(WalletType type) async {
176
+ return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), false]);
177
+ }
178
+
179
+ static Future<Node?> getDefaultForWalletType(WalletType type) async {
180
+ return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), false, true])).firstOrNull;
181
+ }
182
103
- @HiveField(11, defaultValue: false)
183
+ static Future<Node?> getDefaultPowForWalletType(WalletType type) async {
184
+ return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), true, true])).firstOrNull;
185
+ }
186
+
187
+ static Future<List<Node>> getAllForWalletTypePow(WalletType type) async {
188
+ return selectList("typeRaw = ? AND isPow = ?", [serializeToInt(type), true]);
189
+ }
190
+
191
+ static Future<List<Node>> getAllPow() async {
192
+ return selectList("isPow = ?", [true]);
193
+ }
194
+
195
+
196
+ int id;
197
+ late String uriRaw;
198
+ String? login;
199
+ String? password;
200
+ late int typeRaw;
201
+ bool? useSSL;
202
+ bool trusted;
203
+ bool isPow;
204
+ String? socksProxyAddress;
205
+ String? path;
206
+ bool? isElectrs;
207
+ bool? supportsSilentPayments;
208
+ bool? supportsMweb;
209
bool isEnabledForAutoSwitching;
210
+ bool isOfficial;
211
+ bool isBuiltin;
212
+ bool isDefault;
213
106
- @HiveField(12, defaultValue: '')
214
String? label;
215
216
+ static String get tableName => "Node";
217
+ static String get selfIdColumn => "${tableName}Id";
218
+
219
+
220
bool get isSSL => useSSL ?? false;
221
222
bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
@@ -167,18 +278,11 @@ class Node extends HiveObject with Keyable {
278
socksProxyAddress.hashCode ^
279
path.hashCode;
280
170
- @override
171
- dynamic get keyIndex {
172
- _keyIndex ??= key;
173
- return _keyIndex;
174
- }
281
282
WalletType get type => deserializeFromInt(typeRaw);
283
284
set type(WalletType type) => typeRaw = serializeToInt(type);
285
180
- dynamic _keyIndex;
181
-
286
Future<bool> requestNode() async {
287
try {
288
switch (type) {
@@ -228,7 +332,7 @@ class Node extends HiveObject with Keyable {
332
body: jsonBody,
333
);
334
231
-
335
+
336
final resBody = json.decode(response.body) as Map<String, dynamic>;
337
338
return resBody['result']['height'] != null;
cw_core/lib/node_legacy.dart
new
+237
@@ -0,0 +1,237 @@
1
+import 'dart:io';
2
+import 'package:cw_core/keyable.dart';
3
+import 'package:cw_core/node_list.dart';
4
+import 'package:cw_core/utils/proxy_socket/abstract.dart';
5
+import 'package:cw_core/utils/proxy_wrapper.dart';
6
+import 'package:cw_core/utils/print_verbose.dart';
7
+import 'dart:convert';
8
+import 'package:hive/hive.dart';
9
+import 'package:cw_core/hive_type_ids.dart';
10
+import 'package:cw_core/wallet_type.dart';
11
+import 'dart:math' as math;
12
+import 'package:convert/convert.dart';
13
+
14
+import 'package:crypto/crypto.dart';
15
+
16
+import 'cake_hive.dart';
17
+import 'node.dart' as node_new;
18
+
19
+part "node_legacy.g.dart";
20
+
21
+Future<void> performNodeHiveMigration() async {
22
+ if(!CakeHive.isAdapterRegistered(Node.typeId)) {
23
+ CakeHive.registerAdapter(NodeAdapter());
24
+ }
25
+
26
+ final nodeBox = await CakeHive.openBox<Node>(Node.boxName);
27
+ final powNodeBox = await CakeHive.openBox<Node>(Node.boxName+"pow");
28
+ final builtinNodes = await loadAllDefaultNodes();
29
+ final builtinPowNodes = await loadDefaultNanoPowNodes();
30
+ await Node.migrateAllToSqlite(nodeBox, powNodeBox, builtinNodes, builtinPowNodes);
31
+
32
+
33
+}
34
+
35
+Uri createUriFromElectrumAddress(String address, String path) =>
36
+ Uri.tryParse('tcp://$address$path')!;
37
+
38
+@HiveType(typeId: Node.typeId)
39
+class Node extends HiveObject with Keyable {
40
+ Node({
41
+ this.label,
42
+ this.login,
43
+ this.password,
44
+ this.useSSL,
45
+ this.trusted = false,
46
+ this.socksProxyAddress,
47
+ this.path = '',
48
+ this.isEnabledForAutoSwitching = false,
49
+ String? uri,
50
+ WalletType? type,
51
+ }) {
52
+ if (uri != null) {
53
+ uriRaw = uri;
54
+ }
55
+ if (type != null) {
56
+ this.type = type;
57
+ }
58
+ }
59
+
60
+ static Future<void> migrateAllToSqlite(Box<Node> nodeBox, Box<Node> powNodeBox,
61
+ List<node_new.Node> defaultNodes, List<node_new.Node> defaultPowNodes) async {
62
+ final list = nodeBox.values.toList();
63
+ final powList = powNodeBox.values.toList();
64
+ for (final node in list) {
65
+ if(defaultNodes.any((item)=>item.uri == node.uri)) {
66
+ // default nodes will be added by validateBuiltinNodes(), no need to migrate them.
67
+ await node.delete();
68
+ continue;
69
+ }
70
+ await node.migrateToSqlite(
71
+ isPow: false,
72
+ isBuiltin: false,
73
+ isOfficial: false);
74
+ await node.delete();
75
+ }
76
+ for (final node in powList) {
77
+ if(defaultPowNodes.any((item)=>item.uri == node.uri)) {
78
+ await node.delete();
79
+ continue;
80
+ }
81
+ await node.migrateToSqlite(
82
+ isPow: true,
83
+ isBuiltin: false,
84
+ isOfficial: false);
85
+ await node.delete();
86
+ }
87
+ }
88
+
89
+ Future<void> migrateToSqlite({required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
90
+ final newNode = node_new.Node(
91
+ id: key as int,
92
+ login: login,
93
+ label: label,
94
+ password: password,
95
+ type: type,
96
+ useSSL: useSSL,
97
+ trusted: trusted,
98
+ socksProxyAddress: socksProxyAddress,
99
+ isPow: isPow,
100
+ path: path,
101
+ uri: uriRaw,
102
+ isEnabledForAutoSwitching: isEnabledForAutoSwitching,
103
+ isOfficial: isOfficial,
104
+ isBuiltin: isBuiltin,
105
+ );
106
+ await newNode.save();
107
+ }
108
+
109
+
110
+ Node.fromMap(Map<String, Object?> map)
111
+ : uriRaw = map['uri'] as String? ?? '',
112
+ path = map['path'] as String? ?? '',
113
+ login = map['login'] as String?,
114
+ label = map['label'] as String?,
115
+ password = map['password'] as String?,
116
+ useSSL = map['useSSL'] as bool?,
117
+ trusted = map['trusted'] as bool? ?? false,
118
+ socksProxyAddress = map['socksProxyPort'] as String?,
119
+ isEnabledForAutoSwitching = map['isEnabledForAutoSwitching'] as bool? ?? false;
120
+
121
+ static const typeId = NODE_TYPE_ID;
122
+ static const boxName = 'Nodes';
123
+
124
+ @HiveField(0, defaultValue: '')
125
+ late String uriRaw;
126
+
127
+ @HiveField(1)
128
+ String? login;
129
+
130
+ @HiveField(2)
131
+ String? password;
132
+
133
+ @HiveField(3, defaultValue: 0)
134
+ late int typeRaw;
135
+
136
+ @HiveField(4)
137
+ bool? useSSL;
138
+
139
+ @HiveField(5, defaultValue: false)
140
+ bool trusted;
141
+
142
+ @HiveField(6)
143
+ String? socksProxyAddress;
144
+
145
+ @HiveField(7, defaultValue: '')
146
+ String? path;
147
+
148
+ @HiveField(8)
149
+ bool? isElectrs;
150
+
151
+ @HiveField(9)
152
+ bool? supportsSilentPayments;
153
+
154
+ @HiveField(10)
155
+ bool? supportsMweb;
156
+
157
+ @HiveField(11, defaultValue: false)
158
+ bool isEnabledForAutoSwitching;
159
+
160
+ @HiveField(12, defaultValue: '')
161
+ String? label;
162
+
163
+ bool get isSSL => useSSL ?? false;
164
+
165
+ bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
166
+
167
+ Uri get uri {
168
+ switch (type) {
169
+ case WalletType.monero:
170
+ case WalletType.zcash:
171
+ case WalletType.haven:
172
+ case WalletType.wownero:
173
+ return Uri.http(uriRaw, '');
174
+ case WalletType.bitcoin:
175
+ case WalletType.litecoin:
176
+ case WalletType.bitcoinCash:
177
+ case WalletType.dogecoin:
178
+ return createUriFromElectrumAddress(uriRaw, path!);
179
+ case WalletType.nano:
180
+ case WalletType.banano:
181
+ case WalletType.ethereum:
182
+ case WalletType.polygon:
183
+ case WalletType.base:
184
+ case WalletType.bsc:
185
+ case WalletType.arbitrum:
186
+ case WalletType.solana:
187
+ case WalletType.tron:
188
+ case WalletType.zano:
189
+ case WalletType.decred:
190
+ return Uri.parse(
191
+ "http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") || path!.isEmpty ? path : "/$path"}");
192
+ case WalletType.none:
193
+ throw Exception('Unexpected type ${type.toString()} for Node uri');
194
+ }
195
+ }
196
+
197
+ bool get isValidProxyAddress => socksProxyAddress?.contains(':') ?? false;
198
+
199
+ @override
200
+ bool operator ==(other) =>
201
+ other is Node &&
202
+ (other.uriRaw == uriRaw &&
203
+ other.login == login &&
204
+ other.label == label &&
205
+ other.password == password &&
206
+ other.typeRaw == typeRaw &&
207
+ other.useSSL == useSSL &&
208
+ other.trusted == trusted &&
209
+ other.socksProxyAddress == socksProxyAddress &&
210
+ other.path == path);
211
+
212
+ @override
213
+ int get hashCode =>
214
+ uriRaw.hashCode ^
215
+ login.hashCode ^
216
+ label.hashCode ^
217
+ password.hashCode ^
218
+ typeRaw.hashCode ^
219
+ useSSL.hashCode ^
220
+ trusted.hashCode ^
221
+ socksProxyAddress.hashCode ^
222
+ path.hashCode;
223
+
224
+ @override
225
+ dynamic get keyIndex {
226
+ _keyIndex ??= key;
227
+ return _keyIndex;
228
+ }
229
+
230
+ WalletType get type => deserializeFromInt(typeRaw);
231
+
232
+ set type(WalletType type) => typeRaw = serializeToInt(type);
233
+
234
+ dynamic _keyIndex;
235
+
236
+
237
+}
\ No newline at end of file
cw_core/lib/node_list.dart
new
+188
@@ -0,0 +1,188 @@
1
+import 'package:flutter/services.dart';
2
+import 'package:hive/hive.dart';
3
+import "package:yaml/yaml.dart";
4
+import 'package:cw_core/node.dart';
5
+import 'package:cw_core/wallet_type.dart';
6
+
7
+Future<List<Node>> loadDefaultNodes(WalletType type) async {
8
+ String path;
9
+ switch (type) {
10
+ case WalletType.monero:
11
+ path = 'assets/node_list.yml';
12
+ break;
13
+ case WalletType.bitcoin:
14
+ path = 'assets/bitcoin_electrum_server_list.yml';
15
+ break;
16
+ case WalletType.litecoin:
17
+ path = 'assets/litecoin_electrum_server_list.yml';
18
+ break;
19
+ case WalletType.haven:
20
+ path = 'assets/haven_node_list.yml';
21
+ break;
22
+ // TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
23
+ case WalletType.ethereum:
24
+ path = 'assets/ethereum_server_list.yml';
25
+ break;
26
+ case WalletType.nano:
27
+ path = 'assets/nano_node_list.yml';
28
+ break;
29
+ case WalletType.bitcoinCash:
30
+ path = 'assets/bitcoin_cash_electrum_server_list.yml';
31
+ break;
32
+ case WalletType.polygon:
33
+ path = 'assets/polygon_node_list.yml';
34
+ break;
35
+ case WalletType.solana:
36
+ path = 'assets/solana_node_list.yml';
37
+ break;
38
+ case WalletType.tron:
39
+ path = 'assets/tron_node_list.yml';
40
+ break;
41
+ case WalletType.wownero:
42
+ path = 'assets/wownero_node_list.yml';
43
+ break;
44
+ case WalletType.zano:
45
+ path = 'assets/zano_node_list.yml';
46
+ break;
47
+ case WalletType.decred:
48
+ path = 'assets/decred_node_list.yml';
49
+ break;
50
+ case WalletType.dogecoin:
51
+ path = 'assets/dogecoin_electrum_server_list.yml';
52
+ break;
53
+ case WalletType.base:
54
+ path = 'assets/base_node_list.yml';
55
+ break;
56
+ case WalletType.arbitrum:
57
+ path = 'assets/arbitrum_node_list.yml';
58
+ break;
59
+ case WalletType.zcash:
60
+ path = 'assets/zcash_node_list.yml';
61
+ break;
62
+ case WalletType.bsc:
63
+ path = 'assets/bsc_node_list.yml';
64
+ break;
65
+ case WalletType.banano:
66
+ case WalletType.none:
67
+ path = '';
68
+ break;
69
+ }
70
+
71
+ final nodesRaw = await rootBundle.loadString(path);
72
+ final loadedNodes = loadYaml(nodesRaw) as YamlList;
73
+ final nodes = <Node>[];
74
+
75
+ for (final raw in loadedNodes) {
76
+ if (raw is Map) {
77
+ final map = Map.from(raw);
78
+ map["isBuiltin"] = 1;
79
+ map["isOfficial"] = ((map["isOfficial"] as bool? ?? false) ? 1 : 0);
80
+ map["isDefault"] = ((map["isDefault"] as bool? ?? false) ? 1 : 0);
81
+ final node = Node.fromMap(Map<String, Object>.from(map));
82
+ node.type = type;
83
+ nodes.add(node);
84
+ }
85
+ }
86
+
87
+ return nodes;
88
+}
89
+
90
+Future<List<Node>> loadDefaultNanoPowNodes() async {
91
+ final powNodesRaw = await rootBundle.loadString('assets/nano_pow_node_list.yml');
92
+ final loadedPowNodes = loadYaml(powNodesRaw) as YamlList;
93
+ final nodes = <Node>[];
94
+
95
+ for (final raw in loadedPowNodes) {
96
+ if (raw is Map) {
97
+ final node = Node.fromMap(Map<String, Object>.from(raw));
98
+ node.isPow = true;
99
+ node.type = WalletType.nano;
100
+ nodes.add(node);
101
+ }
102
+ }
103
+
104
+ return nodes;
105
+}
106
+
107
+Future<List<Node>> loadAllDefaultNodes() async {
108
+ final moneroNodes = await loadDefaultNodes(WalletType.monero);
109
+ final bitcoinElectrumServerList = await loadDefaultNodes(WalletType.bitcoin);
110
+ final litecoinElectrumServerList = await loadDefaultNodes(WalletType.litecoin);
111
+ final bitcoinCashElectrumServerList = await loadDefaultNodes(WalletType.bitcoinCash);
112
+ final havenNodes = await loadDefaultNodes(WalletType.haven);
113
+ final ethereumNodes = await loadDefaultNodes(WalletType.ethereum);
114
+ final nanoNodes = await loadDefaultNodes(WalletType.nano);
115
+ final polygonNodes = await loadDefaultNodes(WalletType.polygon);
116
+ final solanaNodes = await loadDefaultNodes(WalletType.solana);
117
+ final tronNodes = await loadDefaultNodes(WalletType.tron);
118
+ final decredNodes = await loadDefaultNodes(WalletType.decred);
119
+ final zanoNodes = await loadDefaultNodes(WalletType.zano);
120
+ final dogecoinElectrumServerList = await loadDefaultNodes(WalletType.dogecoin);
121
+ final baseNodes = await loadDefaultNodes(WalletType.base);
122
+ final arbitrumNodes = await loadDefaultNodes(WalletType.arbitrum);
123
+ final zcashNodes = await loadDefaultNodes(WalletType.zcash);
124
+ final bscNodes = await loadDefaultNodes(WalletType.bsc);
125
+
126
+ return moneroNodes +
127
+ bitcoinElectrumServerList +
128
+ litecoinElectrumServerList +
129
+ havenNodes +
130
+ ethereumNodes +
131
+ bitcoinCashElectrumServerList +
132
+ nanoNodes +
133
+ polygonNodes +
134
+ solanaNodes +
135
+ tronNodes +
136
+ zanoNodes +
137
+ decredNodes +
138
+ dogecoinElectrumServerList +
139
+ baseNodes +
140
+ arbitrumNodes +
141
+ zcashNodes +
142
+ bscNodes;
143
+}
144
+
145
+Future<void> resetToDefault() async {
146
+
147
+ final nodes = await loadAllDefaultNodes();
148
+
149
+ final currentNodes = await Node.getAll();
150
+
151
+ // after reset, nodes should retain the id to correspond with the ones in shared prefs.
152
+ // alternative would be nuking the shared prefs on reset
153
+ for (final node in nodes) {
154
+ try {
155
+ final curr = currentNodes.firstWhere(
156
+ (item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
157
+ );
158
+ node.id = curr.id;
159
+ } catch(e) {}
160
+
161
+ }
162
+
163
+ await Node.deleteAll();
164
+ for(final node in nodes) {
165
+ await node.save();
166
+ }
167
+}
168
+
169
+Future<void> resetPowToDefault() async {
170
+ final nanoPowNodes = await loadDefaultNanoPowNodes();
171
+ await Node.deleteAllPow();
172
+ for(final node in nanoPowNodes) {
173
+ node.save();
174
+ }
175
+}
176
+
177
+Future<Node> getDefaultNodeFromFiles(WalletType type, {bool isPow = false}) async {
178
+ final nodes = isPow ? await loadDefaultNanoPowNodes() : await loadDefaultNodes(type);
179
+ try {
180
+ return nodes.firstWhere((item)=>item.isDefault);
181
+ } catch(e) {
182
+ // ideally the yamls would always have a default, but this is better than nothing
183
+ return nodes.first;
184
+ }
185
+}
186
+
187
+
188
+
lib/core/node_switching_service.dart
+7
-9
@@ -14,7 +14,6 @@ class NodeSwitchingService {
14
NodeSwitchingService({
15
required this.appStore,
16
required this.settingsStore,
17
- required this.nodeSource,
17
});
18
19
static const int _healthCheckIntervalSeconds = 30;
@@ -38,7 +37,6 @@ class NodeSwitchingService {
37
38
final AppStore appStore;
39
final SettingsStore settingsStore;
41
- final Box<Node> nodeSource;
40
41
final Map<WalletType, List<dynamic>> _usedNodeKeys = {};
42
@@ -118,13 +116,13 @@ class NodeSwitchingService {
116
WalletType walletType,
117
) async {
118
for (final node in nodes) {
121
- if (!_usedNodeKeys[walletType]!.contains(node.key)) {
119
+ if (!_usedNodeKeys[walletType]!.contains(node.id)) {
120
final isActive = await node.requestNode();
121
if (isActive) {
122
return node;
123
} else {
124
printV('Node ${node.uriRaw} is not active. Marking as used.');
127
- _usedNodeKeys[walletType]!.add(node.key);
125
+ _usedNodeKeys[walletType]!.add(node.id);
126
}
127
}
128
}
@@ -157,7 +155,7 @@ class NodeSwitchingService {
155
final currentNode = settingsStore.getCurrentNode(nodeWalletType, chainId: chainId);
156
157
// Get all trusted nodes for this wallet type
160
- final trustedNodes = nodeSource.values
158
+ final trustedNodes = (await Node.getAll())
159
.where((node) => node.type == nodeWalletType && node.isEnabledForAutoSwitching)
160
.toList();
161
@@ -171,8 +169,8 @@ class NodeSwitchingService {
169
_usedNodeKeys.putIfAbsent(nodeWalletType, () => []);
170
171
// Add current node to used list if not already there
174
- if (!_usedNodeKeys[nodeWalletType]!.contains(currentNode.key)) {
175
- _usedNodeKeys[nodeWalletType]!.add(currentNode.key);
172
+ if (!_usedNodeKeys[nodeWalletType]!.contains(currentNode.id)) {
173
+ _usedNodeKeys[nodeWalletType]!.add(currentNode.id);
174
}
175
176
// Try to find an active unused node
@@ -199,8 +197,8 @@ class NodeSwitchingService {
197
}
198
199
// Ensure the selected node is marked as used
202
- if (!_usedNodeKeys[nodeWalletType]!.contains(nextNode.key)) {
203
- _usedNodeKeys[nodeWalletType]!.add(nextNode.key);
200
+ if (!_usedNodeKeys[nodeWalletType]!.contains(nextNode.id)) {
201
+ _usedNodeKeys[nodeWalletType]!.add(nextNode.id);
202
}
203
204
printV(
lib/di.dart
+19
-26
@@ -326,8 +326,8 @@ import 'src/screens/buy/buy_sell_page.dart';
326
final getIt = GetIt.instance;
327
328
var _isSetupFinished = false;
329
-late Box<Node> _nodeSource;
330
-late Box<Node> _powNodeSource;
329
+// late Box<Node> _nodeSource;
330
+// late Box<Node> _powNodeSource;
331
late Box<Contact> _contactSource;
332
late Box<Template> _templates;
333
late Box<ExchangeTemplate> _exchangeTemplates;
@@ -337,8 +337,6 @@ late Box<UnspentCoinsInfo> _unspentCoinsInfoSource;
337
late Box<PayjoinSession> _payjoinSessionSource;
338
late Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource;
339
Future<void> setup({
340
- required Box<Node> nodeSource,
341
- required Box<Node> powNodeSource,
340
required Box<Contact> contactSource,
341
required Box<Template> templates,
342
required Box<ExchangeTemplate> exchangeTemplates,
@@ -350,8 +348,6 @@ Future<void> setup({
348
required SecureStorage secureStorage,
349
required GlobalKey<NavigatorState> navigatorKey,
350
}) async {
353
- _nodeSource = nodeSource;
354
- _powNodeSource = powNodeSource;
351
_contactSource = contactSource;
352
_templates = templates;
353
_exchangeTemplates = exchangeTemplates;
@@ -376,8 +372,6 @@ Future<void> setup({
372
(secrets.wyreAccountId.isNotEmpty);
373
374
final settingsStore = await SettingsStoreBase.load(
379
- nodeSource: _nodeSource,
380
- powNodeSource: _powNodeSource,
375
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
376
);
377
@@ -385,18 +379,16 @@ Future<void> setup({
379
return;
380
}
381
388
- getIt.registerFactory<Box<Node>>(() => _nodeSource);
389
- getIt.registerFactory<Box<Node>>(() => _powNodeSource, instanceName: Node.boxName + "pow");
382
383
getIt.registerSingleton(AuthenticationStore());
384
getIt.registerSingleton<WalletListStore>(WalletListStore());
393
- getIt.registerSingleton(NodeListStoreBase.instance);
385
+ // getIt.registerSingleton(NodeListStoreBase.instance);
386
getIt.registerSingleton<SettingsStore>(settingsStore);
387
getIt.registerSingleton<AppStore>(AppStore(
388
authenticationStore: getIt.get<AuthenticationStore>(),
389
walletList: getIt.get<WalletListStore>(),
390
settingsStore: getIt.get<SettingsStore>(),
399
- nodeListStore: getIt.get<NodeListStore>(),
391
+ // nodeListStore: getIt.get<NodeListStore>(),
392
themeStore: getIt.get<ThemeStore>()));
393
getIt.registerSingleton<TradesStore>(
394
TradesStore(appStore: getIt.get<AppStore>()));
@@ -1126,22 +1118,22 @@ Future<void> setup({
1118
1119
getIt.registerFactory(() => AddressListPage(getIt.get<WalletAddressListViewModel>()));
1120
1121
+ getIt.registerLazySingleton(() {
1122
+ final appStore = getIt.get<AppStore>();
1123
+ return NodeListViewModel(appStore);
1124
+ });
1125
+
1126
getIt.registerFactoryParam<NewAddressesPage, bool, void>(
1130
- (showHidden, _) => NewAddressesPage(
1127
+ (showHidden, _) => NewAddressesPage(
1128
showHidden: showHidden,
1129
addressListViewModel: getIt<WalletAddressListViewModel>(),
1130
dashboardViewModel: getIt<DashboardViewModel>(),
1131
),
1132
);
1133
1137
- getIt.registerFactory(() {
1134
+ getIt.registerLazySingleton(() {
1135
final appStore = getIt.get<AppStore>();
1139
- return NodeListViewModel(_nodeSource, appStore);
1140
- });
1141
-
1142
- getIt.registerFactory(() {
1143
- final appStore = getIt.get<AppStore>();
1144
- return PowNodeListViewModel(_powNodeSource, appStore);
1136
+ return PowNodeListViewModel(appStore);
1137
});
1138
1139
getIt.registerFactory(() => ConnectionSyncViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
@@ -1184,12 +1176,14 @@ Future<void> setup({
1176
final WalletType type = args['type'] as WalletType? ?? getIt.get<AppStore>().wallet!.type;
1177
final bool isPow = args['isPow'] as bool? ?? false;
1178
final Node? editingNode = args['editingNode'] as Node?;
1187
- final nodeSourceArgs = isPow ? _powNodeSource : _nodeSource;
1179
return NodeCreateOrEditViewModel(
1189
- nodeSourceArgs,
1190
- type,
1191
- editingNode,
1192
- getIt.get<SettingsStore>());
1180
+ isPow,
1181
+ getIt.get<NodeListViewModel>(),
1182
+ getIt.get<PowNodeListViewModel>(),
1183
+ type,
1184
+ getIt.get<SettingsStore>(),
1185
+ editingNode: editingNode
1186
+ );
1187
}
1188
);
1189
@@ -1791,7 +1785,6 @@ Future<void> setup({
1785
getIt.registerLazySingleton(() => NodeSwitchingService(
1786
appStore: getIt.get<AppStore>(),
1787
settingsStore: getIt.get<SettingsStore>(),
1794
- nodeSource: _nodeSource,
1788
));
1789
1790
getIt.registerFactoryParam<BridgeAmountPage, CryptoCurrency, void>(
lib/entities/default_settings_migration.dart
+119
-372
@@ -18,6 +18,7 @@ import 'package:cake_wallet/wownero/wownero.dart';
18
import 'package:collection/collection.dart';
19
import 'package:cw_core/node.dart';
20
import 'package:cake_wallet/entities/sync_status_display_mode.dart';
21
+import 'package:cw_core/node_list.dart';
22
import 'package:cw_core/pathForWallet.dart';
23
import 'package:cw_core/root_dir.dart';
24
import 'package:cw_core/spl_token.dart';
@@ -61,8 +62,6 @@ Future<void> defaultSettingsMigration(
62
{required int version,
63
required SharedPreferences sharedPreferences,
64
required SecureStorage secureStorage,
64
- required Box<Node> nodes,
65
- required Box<Node> powNodes,
65
required Box<Contact> contactSource,
66
required Box<HavenSeedStore> havenSeedStore}) async {
67
if (Platform.isIOS) {
@@ -70,7 +69,7 @@ Future<void> defaultSettingsMigration(
69
}
70
71
// check current nodes for nullability regardless of the version
73
- await checkCurrentNodes(nodes, powNodes, sharedPreferences);
72
+ // await checkCurrentNodes(sharedPreferences);
73
74
final isNewInstall =
75
sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
@@ -103,10 +102,9 @@ Future<void> defaultSettingsMigration(
102
await sharedPreferences.setInt(
103
PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw);
104
await sharedPreferences.setBool('save_recipient_address', true);
106
- await resetToDefault(nodes);
105
+ await resetToDefault();
106
107
await _changeDefaultNode(
109
- nodes: nodes,
108
sharedPreferences: sharedPreferences,
109
type: WalletType.monero,
110
currentNodePreferenceKey: PreferencesKey.currentNodeIdKey,
@@ -114,30 +112,26 @@ Future<void> defaultSettingsMigration(
112
trusted: true,
113
);
114
await _changeDefaultNode(
117
- nodes: nodes,
115
sharedPreferences: sharedPreferences,
116
type: WalletType.bitcoin,
117
currentNodePreferenceKey: PreferencesKey.currentBitcoinElectrumSererIdKey,
118
useSSL: true,
119
);
120
await _changeDefaultNode(
124
- nodes: nodes,
121
sharedPreferences: sharedPreferences,
122
type: WalletType.litecoin,
123
currentNodePreferenceKey: PreferencesKey.currentLitecoinElectrumSererIdKey,
124
useSSL: true,
125
);
126
await _changeDefaultNode(
131
- nodes: nodes,
127
sharedPreferences: sharedPreferences,
128
type: WalletType.haven,
129
currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
130
);
131
break;
132
case 2:
138
- await replaceNodesMigration(nodes: nodes);
133
+ await replaceNodesMigration();
134
await _changeDefaultNode(
140
- nodes: nodes,
135
sharedPreferences: sharedPreferences,
136
type: WalletType.monero,
137
newDefaultUri: newCakeWalletMoneroUri,
@@ -152,13 +146,12 @@ Future<void> defaultSettingsMigration(
146
);
147
break;
148
case 3:
155
- await updateNodeTypes(nodes: nodes);
156
- await addWalletNodeList(nodes: nodes, type: WalletType.bitcoin);
149
+ await updateNodeTypes();
150
+ await addWalletNodeList(type: WalletType.bitcoin);
151
152
break;
153
case 4:
154
await _changeDefaultNode(
161
- nodes: nodes,
155
sharedPreferences: sharedPreferences,
156
type: WalletType.bitcoin,
157
newDefaultUri: newCakeWalletBitcoinUri,
@@ -185,7 +178,6 @@ Future<void> defaultSettingsMigration(
178
179
case 11:
180
await _changeDefaultNode(
188
- nodes: nodes,
181
sharedPreferences: sharedPreferences,
182
type: WalletType.monero,
183
newDefaultUri: newCakeWalletMoneroUri,
@@ -196,38 +188,35 @@ Future<void> defaultSettingsMigration(
188
break;
189
190
case 12:
199
- await checkCurrentNodes(nodes, powNodes, sharedPreferences);
191
+ // await checkCurrentNodes(sharedPreferences);
192
break;
193
194
case 13:
203
- await resetBitcoinElectrumServer(nodes, sharedPreferences);
195
+ await resetBitcoinElectrumServer(sharedPreferences);
196
break;
197
198
case 15:
207
- await addWalletNodeList(nodes: nodes, type: WalletType.litecoin);
199
+ await addWalletNodeList(type: WalletType.litecoin);
200
await _changeDefaultNode(
209
- nodes: nodes,
201
sharedPreferences: sharedPreferences,
202
type: WalletType.litecoin,
203
currentNodePreferenceKey: PreferencesKey.currentLitecoinElectrumSererIdKey,
204
);
214
- await checkCurrentNodes(nodes, powNodes, sharedPreferences);
205
+ // await checkCurrentNodes(sharedPreferences);
206
break;
207
208
case 16:
218
- await addWalletNodeList(nodes: nodes, type: WalletType.haven);
209
+ await addWalletNodeList(type: WalletType.haven);
210
await _changeDefaultNode(
220
- nodes: nodes,
211
sharedPreferences: sharedPreferences,
212
type: WalletType.haven,
213
currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
214
);
225
- await checkCurrentNodes(nodes, powNodes, sharedPreferences);
215
+ // await checkCurrentNodes(sharedPreferences);
216
break;
217
218
case 17:
219
await _changeDefaultNode(
230
- nodes: nodes,
220
sharedPreferences: sharedPreferences,
221
type: WalletType.haven,
222
currentNodePreferenceKey: PreferencesKey.currentHavenNodeIdKey,
@@ -235,7 +224,7 @@ Future<void> defaultSettingsMigration(
224
break;
225
226
case 18:
238
- addWalletNodeList(nodes: nodes, type: WalletType.monero);
227
+ addWalletNodeList(type: WalletType.monero);
228
break;
229
230
case 19:
@@ -245,25 +234,22 @@ Future<void> defaultSettingsMigration(
234
await migrateExchangeStatus(sharedPreferences);
235
break;
236
case 21:
248
- await addWalletNodeList(nodes: nodes, type: WalletType.ethereum);
237
+ await addWalletNodeList(type: WalletType.ethereum);
238
await _changeDefaultNode(
250
- nodes: nodes,
239
sharedPreferences: sharedPreferences,
240
type: WalletType.ethereum,
241
currentNodePreferenceKey: PreferencesKey.currentEthereumNodeIdKey,
242
);
243
break;
244
case 22:
257
- await addWalletNodeList(nodes: nodes, type: WalletType.nano);
258
- await addNanoPowNodeList(nodes: powNodes);
245
+ await addWalletNodeList(type: WalletType.nano);
246
+ await addNanoPowNodeList();
247
await _changeDefaultNode(
260
- nodes: nodes,
248
sharedPreferences: sharedPreferences,
249
type: WalletType.nano,
250
currentNodePreferenceKey: PreferencesKey.currentNanoNodeIdKey,
251
);
252
await _changeDefaultNode(
266
- nodes: powNodes,
253
sharedPreferences: sharedPreferences,
254
type: WalletType.nano,
255
currentNodePreferenceKey: PreferencesKey.currentNanoPowNodeIdKey,
@@ -271,18 +257,16 @@ Future<void> defaultSettingsMigration(
257
);
258
break;
259
case 23:
274
- await addWalletNodeList(nodes: nodes, type: WalletType.bitcoinCash);
260
+ await addWalletNodeList(type: WalletType.bitcoinCash);
261
await _changeDefaultNode(
276
- nodes: nodes,
262
sharedPreferences: sharedPreferences,
263
type: WalletType.bitcoinCash,
264
currentNodePreferenceKey: PreferencesKey.currentBitcoinCashNodeIdKey,
265
);
266
break;
267
case 24:
283
- await addWalletNodeList(nodes: nodes, type: WalletType.polygon);
268
+ await addWalletNodeList(type: WalletType.polygon);
269
await _changeDefaultNode(
285
- nodes: nodes,
270
sharedPreferences: sharedPreferences,
271
type: WalletType.polygon,
272
currentNodePreferenceKey: PreferencesKey.currentPolygonNodeIdKey,
@@ -299,9 +283,8 @@ Future<void> defaultSettingsMigration(
283
// await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences);
284
break;
285
case 27:
302
- await addWalletNodeList(nodes: nodes, type: WalletType.solana);
286
+ await addWalletNodeList( type: WalletType.solana);
287
await _changeDefaultNode(
304
- nodes: nodes,
288
sharedPreferences: sharedPreferences,
289
type: WalletType.solana,
290
currentNodePreferenceKey: PreferencesKey.currentSolanaNodeIdKey,
@@ -313,7 +296,6 @@ Future<void> defaultSettingsMigration(
296
break;
297
case 29:
298
await _changeDefaultNode(
316
- nodes: nodes,
299
sharedPreferences: sharedPreferences,
300
type: WalletType.bitcoin,
301
newDefaultUri: newCakeWalletBitcoinUri,
@@ -326,25 +308,23 @@ Future<void> defaultSettingsMigration(
308
await disableServiceStatusFiatDisabled(sharedPreferences);
309
break;
310
case 31:
329
- await updateNanoNodeList(nodes: nodes);
311
+ await updateNanoNodeList();
312
break;
313
case 32:
314
await updateBtcNanoWalletInfos();
315
break;
316
case 33:
335
- await addWalletNodeList(nodes: nodes, type: WalletType.tron);
317
+ await addWalletNodeList(type: WalletType.tron);
318
await _changeDefaultNode(
337
- nodes: nodes,
319
sharedPreferences: sharedPreferences,
320
type: WalletType.tron,
321
currentNodePreferenceKey: PreferencesKey.currentTronNodeIdKey,
322
);
323
break;
324
case 34:
344
- addWalletNodeList(nodes: nodes, type: WalletType.bitcoin);
325
+ addWalletNodeList(type: WalletType.bitcoin);
326
case 35:
327
await _changeDefaultNode(
347
- nodes: nodes,
328
sharedPreferences: sharedPreferences,
329
type: WalletType.bitcoin,
330
newDefaultUri: newCakeWalletBitcoinUri,
@@ -354,9 +334,8 @@ Future<void> defaultSettingsMigration(
334
);
335
break;
336
case 36:
357
- await addWalletNodeList(nodes: nodes, type: WalletType.wownero);
337
+ await addWalletNodeList(type: WalletType.wownero);
338
await _changeDefaultNode(
359
- nodes: nodes,
339
sharedPreferences: sharedPreferences,
340
type: WalletType.wownero,
341
currentNodePreferenceKey: PreferencesKey.currentWowneroNodeIdKey,
@@ -370,9 +349,8 @@ Future<void> defaultSettingsMigration(
349
await fixBtcDerivationPaths();
350
break;
351
case 39:
373
- _fixNodesUseSSLFlag(nodes);
352
+ _fixNodesUseSSLFlag();
353
await _changeDefaultNode(
375
- nodes: nodes,
354
sharedPreferences: sharedPreferences,
355
type: WalletType.nano,
356
newDefaultUri: nanoDefaultNodeUri,
@@ -382,7 +360,7 @@ Future<void> defaultSettingsMigration(
360
);
361
break;
362
case 40:
385
- await removeMoneroWorld(sharedPreferences: sharedPreferences, nodes: nodes);
363
+ await removeMoneroWorld(sharedPreferences: sharedPreferences);
364
break;
365
case 41:
366
_changeExchangeProviderAvailability(
@@ -390,14 +368,14 @@ Future<void> defaultSettingsMigration(
368
providerName: "SwapTrade",
369
enabled: false,
370
);
393
- addWalletNodeList(nodes: nodes, type: WalletType.bitcoin);
394
- addWalletNodeList(nodes: nodes, type: WalletType.tron);
371
+ addWalletNodeList(type: WalletType.bitcoin);
372
+ addWalletNodeList(type: WalletType.tron);
373
break;
374
case 42:
397
- _fixNodesUseSSLFlag(nodes);
375
+ _fixNodesUseSSLFlag();
376
break;
377
case 43:
400
- _fixNodesUseSSLFlag(nodes);
378
+ _fixNodesUseSSLFlag();
379
_changeExchangeProviderAvailability(
380
sharedPreferences,
381
providerName: "THORChain",
@@ -410,9 +388,8 @@ Future<void> defaultSettingsMigration(
388
);
389
break;
390
case 44:
413
- _fixNodesUseSSLFlag(nodes);
391
+ _fixNodesUseSSLFlag();
392
await _changeDefaultNode(
415
- nodes: nodes,
393
sharedPreferences: sharedPreferences,
394
type: WalletType.bitcoin,
395
newDefaultUri: newCakeWalletBitcoinUri,
@@ -421,7 +398,6 @@ Future<void> defaultSettingsMigration(
398
oldUri: ['cakewallet.com'],
399
);
400
_changeDefaultNode(
424
- nodes: nodes,
401
sharedPreferences: sharedPreferences,
402
type: WalletType.tron,
403
newDefaultUri: tronDefaultNodeUri,
@@ -436,10 +412,9 @@ Future<void> defaultSettingsMigration(
412
case 45:
413
// await _backupHavenSeeds(havenSeedStore);
414
439
- addWalletNodeList(nodes: nodes, type: WalletType.polygon);
440
- addWalletNodeList(nodes: nodes, type: WalletType.ethereum);
415
+ addWalletNodeList(type: WalletType.polygon);
416
+ addWalletNodeList(type: WalletType.ethereum);
417
_changeDefaultNode(
442
- nodes: nodes,
418
sharedPreferences: sharedPreferences,
419
type: WalletType.tron,
420
newDefaultUri: tronDefaultNodeUri,
@@ -451,7 +426,6 @@ Future<void> defaultSettingsMigration(
426
],
427
);
428
_changeDefaultNode(
454
- nodes: nodes,
429
sharedPreferences: sharedPreferences,
430
type: WalletType.solana,
431
newDefaultUri: solanaDefaultNodeUri,
@@ -461,10 +435,9 @@ Future<void> defaultSettingsMigration(
435
);
436
break;
437
case 46:
464
- await _fixNodesUseSSLFlag(nodes);
465
- await addWalletNodeList(nodes: nodes, type: WalletType.litecoin);
438
+ await _fixNodesUseSSLFlag();
439
+ await addWalletNodeList(type: WalletType.litecoin);
440
await _changeDefaultNode(
467
- nodes: nodes,
441
sharedPreferences: sharedPreferences,
442
type: WalletType.solana,
443
newDefaultUri: solanaDefaultNodeUri,
@@ -477,21 +450,18 @@ Future<void> defaultSettingsMigration(
450
],
451
);
452
await _updateNode(
480
- nodes: nodes,
453
currentUri: "ethereum.publicnode.com",
454
newUri: "ethereum-rpc.publicnode.com",
455
useSSL: true,
456
);
457
await _updateNode(
486
- nodes: nodes,
458
currentUri: "polygon-bor.publicnode.com",
459
newUri: "polygon-bor-rpc.publicnode.com",
460
useSSL: true,
461
);
462
case 47:
492
- await addWalletNodeList(nodes: nodes, type: WalletType.zano);
463
+ await addWalletNodeList(type: WalletType.zano);
464
await _changeDefaultNode(
494
- nodes: nodes,
465
sharedPreferences: sharedPreferences,
466
type: WalletType.zano,
467
currentNodePreferenceKey: PreferencesKey.currentZanoNodeIdKey,
@@ -508,9 +478,8 @@ Future<void> defaultSettingsMigration(
478
);
479
break;
480
case 48:
511
- await addWalletNodeList(nodes: nodes, type: WalletType.decred);
481
+ await addWalletNodeList(type: WalletType.decred);
482
await _changeDefaultNode(
513
- nodes: nodes,
483
sharedPreferences: sharedPreferences,
484
type: WalletType.decred,
485
currentNodePreferenceKey: PreferencesKey.currentDecredNodeIdKey,
@@ -524,36 +493,32 @@ Future<void> defaultSettingsMigration(
493
);
494
break;
495
case 50:
527
- migrateExistingNodesToUseAutoSwitching(nodes: nodes, powNodes: powNodes);
496
+ migrateExistingNodesToUseAutoSwitching();
497
break;
498
case 51:
499
_changeDefaultNode(
531
- nodes: nodes,
500
sharedPreferences: sharedPreferences,
501
type: WalletType.zano,
502
currentNodePreferenceKey: PreferencesKey.currentZanoNodeIdKey,
503
);
536
- await addWalletNodeList(nodes: nodes, type: WalletType.dogecoin);
504
+ await addWalletNodeList(type: WalletType.dogecoin);
505
await _changeDefaultNode(
538
- nodes: nodes,
506
sharedPreferences: sharedPreferences,
507
type: WalletType.dogecoin,
508
currentNodePreferenceKey: PreferencesKey.currentDogecoinNodeIdKey,
509
);
510
break;
511
case 52:
545
- await addWalletNodeList(nodes: nodes, type: WalletType.base);
512
+ await addWalletNodeList(type: WalletType.base);
513
await _changeDefaultNode(
547
- nodes: nodes,
514
sharedPreferences: sharedPreferences,
515
type: WalletType.base,
516
currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
517
);
518
break;
553
- case 53:
554
- await addWalletNodeList(nodes: nodes, type: WalletType.arbitrum);
519
+ case 53:
520
+ await addWalletNodeList(type: WalletType.arbitrum);
521
await _changeDefaultNode(
556
- nodes: nodes,
522
sharedPreferences: sharedPreferences,
523
type: WalletType.arbitrum,
524
currentNodePreferenceKey: PreferencesKey.currentArbitrumNodeIdKey,
@@ -563,9 +528,8 @@ Future<void> defaultSettingsMigration(
528
await _backupWowneroSeeds(havenSeedStore);
529
break;
530
case 55:
566
- await addWalletNodeList(nodes: nodes, type: WalletType.zcash);
531
+ await addWalletNodeList(type: WalletType.zcash);
532
await _changeDefaultNode(
568
- nodes: nodes,
533
sharedPreferences: sharedPreferences,
534
type: WalletType.zcash,
535
currentNodePreferenceKey: PreferencesKey.currentZcashNodeIdKey,
@@ -577,9 +541,8 @@ Future<void> defaultSettingsMigration(
541
case 57:
542
await _addXautTokenToExistingEthereumWallets();
543
580
- await addWalletNodeList(nodes: nodes, type: WalletType.bsc);
544
+ await addWalletNodeList(type: WalletType.bsc);
545
await _changeDefaultNode(
582
- nodes: nodes,
546
sharedPreferences: sharedPreferences,
547
type: WalletType.bsc,
548
currentNodePreferenceKey: PreferencesKey.currentBscNodeIdKey,
@@ -624,13 +587,18 @@ Future<void> defaultSettingsMigration(
587
break;
588
case 65:
589
await _changeDefaultNode(
627
- nodes: nodes,
590
sharedPreferences: sharedPreferences,
591
type: WalletType.base,
592
currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
593
oldUri: ['base.nownodes.io'],
594
);
595
break;
596
+ case 66:
597
+ await _changeDefaultNode(
598
+ sharedPreferences: sharedPreferences,
599
+ type: WalletType.arbitrum,
600
+ currentNodePreferenceKey: PreferencesKey.currentArbitrumNodeIdKey,
601
+ oldUri: ["arbitrum.nownodes.io"]);
602
default:
603
break;
604
}
@@ -647,12 +615,13 @@ Future<void> defaultSettingsMigration(
615
}
616
617
Future<void> _updateNode({
650
- required Box<Node> nodes,
618
required String currentUri,
619
String? newUri,
620
bool? useSSL,
621
}) async {
655
- for (Node node in nodes.values) {
622
+ final nodes = await Node.getAll();
623
+
624
+ for (Node node in nodes) {
625
if (node.uriRaw == currentUri) {
626
if (newUri != null) {
627
node.uriRaw = newUri;
@@ -668,7 +637,6 @@ Future<void> _updateNode({
637
/// generic function for changing any wallet default node
638
/// instead of making a new function for each change
639
Future<void> _changeDefaultNode({
671
- required Box<Node> nodes,
640
required SharedPreferences sharedPreferences,
641
required WalletType type,
642
required String currentNodePreferenceKey,
@@ -678,19 +646,21 @@ Future<void> _changeDefaultNode({
646
List<String>?
647
oldUri, // ignore, if you want to force replace the node regardless of the user's current node
648
}) async {
649
+ List<Node> nodes = await Node.getAll();
650
+
651
final currentNodeId = sharedPreferences.getInt(currentNodePreferenceKey);
652
final bool shouldReplace;
653
if (currentNodeId == null) {
654
shouldReplace = true;
655
} else {
686
- final currentNode = nodes.values.firstWhere((node) => node.key == currentNodeId);
687
- shouldReplace = oldUri?.any((e) => currentNode.uriRaw.contains(e)) ?? true;
656
+ final currentNode = nodes.firstWhereOrNull((node) => node.id == currentNodeId);
657
+ shouldReplace = currentNode == null || oldUri?.any((e) => currentNode!.uriRaw.contains(e)) ?? true;
658
}
659
660
if (shouldReplace) {
691
- newDefaultUri ??= _getDefaultNodeUri(type);
661
+ newDefaultUri ??= (await getDefaultNodeFromFiles(type)).uriRaw;
662
var newNodeId =
693
- nodes.values.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.key;
663
+ nodes.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.id;
664
665
// new node doesn't exist, then add it
666
if (newNodeId == null) {
@@ -701,55 +671,11 @@ Future<void> _changeDefaultNode({
671
trusted: trusted,
672
);
673
704
- await nodes.add(newNode);
705
- newNodeId = newNode.key;
674
+ await newNode.save();
675
+ newNodeId = newNode.id;
676
}
677
708
- await sharedPreferences.setInt(currentNodePreferenceKey, newNodeId as int);
709
- }
710
-}
711
-
712
-String _getDefaultNodeUri(WalletType type) {
713
- switch (type) {
714
- case WalletType.monero:
715
- return newCakeWalletMoneroUri;
716
- case WalletType.bitcoin:
717
- return newCakeWalletBitcoinUri;
718
- case WalletType.litecoin:
719
- return cakeWalletLitecoinElectrumUri;
720
- case WalletType.haven:
721
- return havenDefaultNodeUri;
722
- case WalletType.ethereum:
723
- return ethereumDefaultNodeUri;
724
- case WalletType.nano:
725
- return nanoDefaultNodeUri;
726
- case WalletType.bitcoinCash:
727
- return cakeWalletBitcoinCashDefaultNodeUri;
728
- case WalletType.polygon:
729
- return polygonDefaultNodeUri;
730
- case WalletType.solana:
731
- return solanaDefaultNodeUri;
732
- case WalletType.tron:
733
- return tronDefaultNodeUri;
734
- case WalletType.wownero:
735
- return wowneroDefaultNodeUri;
736
- case WalletType.zano:
737
- return zanoDefaultNodeUri;
738
- case WalletType.decred:
739
- return decredDefaultUri;
740
- case WalletType.dogecoin:
741
- return dogecoinDefaultNodeUri;
742
- case WalletType.base:
743
- return baseDefaultNodeUri;
744
- case WalletType.arbitrum:
745
- return arbitrumDefaultNodeUri;
746
- case WalletType.bsc:
747
- return bscDefaultNodeUri;
748
- case WalletType.zcash:
749
- return zcashDefaultNodeUri;
750
- case WalletType.banano:
751
- case WalletType.none:
752
- return '';
678
+ await sharedPreferences.setInt(currentNodePreferenceKey, newNodeId);
679
}
680
}
681
@@ -767,8 +693,9 @@ Future<void> _changeExchangeProviderAvailability(SharedPreferences sharedPrefere
693
);
694
}
695
770
-Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async {
771
- for (Node node in nodes.values) {
696
+Future<void> _fixNodesUseSSLFlag() async {
697
+ final nodes = await Node.getAll();
698
+ for (Node node in nodes) {
699
switch (node.uriRaw) {
700
case cakeWalletLitecoinElectrumUri:
701
case cakeWalletBitcoinElectrumUri:
@@ -781,7 +708,8 @@ Future<void> _fixNodesUseSSLFlag(Box<Node> nodes) async {
708
}
709
}
710
784
-Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
711
+Future<void> updateNanoNodeList() async {
712
+ final nodes = await Node.getAll();
713
final nodeList = await loadDefaultNodes(WalletType.nano);
714
var listOfNewEndpoints = <String>[
715
"app.natrium.io",
@@ -792,14 +720,14 @@ Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
720
];
721
// add new nodes:
722
for (final node in nodeList) {
795
- if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.values.contains(node)) {
796
- await nodes.add(node);
723
+ if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.contains(node)) {
724
+ await node.save();
725
}
726
}
727
728
// update the nautilus node:
729
final nautilusNode =
802
- nodes.values.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
730
+ nodes.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
731
if (nautilusNode != null) {
732
nautilusNode.uriRaw = "node.nautilus.io";
733
nautilusNode.path = "/api";
@@ -916,16 +844,17 @@ Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPre
844
}
845
}
846
919
-Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
847
+Future<void> replaceNodesMigration() async {
848
final replaceNodes = <String, Node>{
849
'eu-node.cakewallet.io:18081':
922
- Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
850
+ Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
851
'node.cakewallet.io:18081':
924
- Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
852
+ Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
853
'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081', type: WalletType.monero)
854
};
855
928
- nodes.values.forEach((Node node) async {
856
+ List<Node> nodes = await Node.getAll();
857
+ nodes.forEach((Node node) async {
858
final nodeToReplace = replaceNodes[node.uri];
859
860
if (nodeToReplace != null) {
@@ -937,16 +866,12 @@ Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
866
});
867
}
868
940
-Node? getBitcoinTestnetDefaultElectrumServer({required Box<Node> nodes}) {
941
- return nodes.values
942
- .firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
943
- nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
944
-}
869
+Future<Node?> getBitcoinTestnetDefaultElectrumServer()async {
870
+ final nodes = await Node.getAll();
871
946
-Node? getDefaultNode({required Box<Node> nodes, required WalletType type}) {
947
- final defaultUri = _getDefaultNodeUri(type);
948
- return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == defaultUri) ??
949
- nodes.values.firstWhereOrNull((node) => node.type == type);
872
+ return nodes
873
+ .firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
874
+ nodes.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
875
}
876
877
Future<void> insecureStorageMigration({
@@ -1057,8 +982,9 @@ Future<void> rewriteSecureStoragePin({required SecureStorage secureStorage}) asy
982
);
983
}
984
1060
-Future<void> updateNodeTypes({required Box<Node> nodes}) async {
1061
- nodes.values.forEach((node) async {
985
+Future<void> updateNodeTypes() async {
986
+ List<Node> nodes = await Node.getAll();
987
+ nodes.forEach((node) async {
988
if (node.type == null) {
989
node.type = WalletType.monero;
990
await node.save();
@@ -1146,206 +1072,13 @@ Future<void> updateBtcNanoWalletInfos() async {}
1072
// }
1073
// }
1074
1149
-Future<void> checkCurrentNodes(
1150
- Box<Node> nodeSource, Box<Node> powNodeSource, SharedPreferences sharedPreferences) async {
1151
- final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
1152
- final currentBitcoinElectrumSeverId =
1153
- sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
1154
- final currentLitecoinElectrumSeverId =
1155
- sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
1156
- final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
1157
- final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
1158
- final currentPolygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
1159
- final currentBaseNodeId = sharedPreferences.getInt(PreferencesKey.currentBaseNodeIdKey);
1160
- final currentArbitrumNodeId = sharedPreferences.getInt(PreferencesKey.currentArbitrumNodeIdKey);
1161
- final currentBscNodeId = sharedPreferences.getInt(PreferencesKey.currentBscNodeIdKey);
1162
- final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
1163
- final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
1164
- final currentDecredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
1165
- final currentBitcoinCashNodeId =
1166
- sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
1167
- final currentDogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
1168
- final currentSolanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
1169
- final currentTronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
1170
- final currentWowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
1171
- final currentZanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
1172
- final currentZcashNodeId = sharedPreferences.getInt(PreferencesKey.currentZcashNodeIdKey);
1173
- final currentMoneroNode =
1174
- nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
1175
- final currentBitcoinElectrumServer =
1176
- nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId);
1177
- final currentLitecoinElectrumServer =
1178
- nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId);
1179
- final currentHavenNodeServer =
1180
- nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId);
1181
- final currentEthereumNodeServer =
1182
- nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
1183
- final currentPolygonNodeServer =
1184
- nodeSource.values.firstWhereOrNull((node) => node.key == currentPolygonNodeId);
1185
- final currentBaseNodeServer =
1186
- nodeSource.values.firstWhereOrNull((node) => node.key == currentBaseNodeId);
1187
- final currentArbitrumNodeServer =
1188
- nodeSource.values.firstWhereOrNull((node) => node.key == currentArbitrumNodeId);
1189
- final currentBscNodeServer =
1190
- nodeSource.values.firstWhereOrNull((node) => node.key == currentBscNodeId);
1191
- final currentNanoNodeServer =
1192
- nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
1193
- final currentDecredNodeServer =
1194
- nodeSource.values.firstWhereOrNull((node) => node.key == currentDecredNodeId);
1195
- final currentNanoPowNodeServer =
1196
- powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
1197
- final currentBitcoinCashNodeServer =
1198
- nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId);
1199
- final currentDogecoinNodeServer =
1200
- nodeSource.values.firstWhereOrNull((node) => node.key == currentDogecoinNodeId);
1201
- final currentSolanaNodeServer =
1202
- nodeSource.values.firstWhereOrNull((node) => node.key == currentSolanaNodeId);
1203
- final currentTronNodeServer =
1204
- nodeSource.values.firstWhereOrNull((node) => node.key == currentTronNodeId);
1205
- final currentWowneroNodeServer =
1206
- nodeSource.values.firstWhereOrNull((node) => node.key == currentWowneroNodeId);
1207
- final currentZanoNode =
1208
- nodeSource.values.firstWhereOrNull((node) => node.key == currentZanoNodeId);
1209
- final currentZcashNode =
1210
- nodeSource.values.firstWhereOrNull((node) => node.key == currentZcashNodeId);
1211
-
1212
- if (currentMoneroNode == null) {
1213
- final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
1214
- await nodeSource.add(newCakeWalletNode);
1215
- await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int);
1216
- }
1217
-
1218
- if (currentBitcoinElectrumServer == null) {
1219
- final cakeWalletElectrum = Node(
1220
- uri: cakeWalletBitcoinElectrumUri,
1221
- type: WalletType.bitcoin,
1222
- useSSL: false,
1223
- isEnabledForAutoSwitching: true);
1224
- await nodeSource.add(cakeWalletElectrum);
1225
- final cakeWalletElectrumTestnet =
1226
- Node(uri: publicBitcoinTestnetElectrumUri, type: WalletType.bitcoin, useSSL: false);
1227
- await nodeSource.add(cakeWalletElectrumTestnet);
1228
- await sharedPreferences.setInt(
1229
- PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletElectrum.key as int);
1230
- }
1231
-
1232
- if (currentLitecoinElectrumServer == null) {
1233
- final cakeWalletElectrum =
1234
- Node(uri: cakeWalletLitecoinElectrumUri, type: WalletType.litecoin, useSSL: false);
1235
- await nodeSource.add(cakeWalletElectrum);
1236
- await sharedPreferences.setInt(
1237
- PreferencesKey.currentLitecoinElectrumSererIdKey, cakeWalletElectrum.key as int);
1238
- }
1239
-
1240
- if (currentHavenNodeServer == null) {
1241
- final node = Node(uri: havenDefaultNodeUri, type: WalletType.haven);
1242
- await nodeSource.add(node);
1243
- await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.key as int);
1244
- }
1245
-
1246
- if (currentEthereumNodeServer == null) {
1247
- final node = Node(uri: ethereumDefaultNodeUri, type: WalletType.ethereum);
1248
- await nodeSource.add(node);
1249
- await sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int);
1250
- }
1251
-
1252
- if (currentNanoNodeServer == null) {
1253
- final node = Node(uri: nanoDefaultNodeUri, useSSL: true, type: WalletType.nano);
1254
- await nodeSource.add(node);
1255
- await sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
1256
- }
1257
-
1258
- if (currentNanoPowNodeServer == null) {
1259
- Node? node = powNodeSource.values
1260
- .firstWhereOrNull((node) => node.uri.toString() == nanoDefaultPowNodeUri);
1261
- if (node == null) {
1262
- node = Node(uri: nanoDefaultPowNodeUri, useSSL: true, type: WalletType.nano);
1263
- await powNodeSource.add(node);
1264
- }
1265
- await sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.key as int);
1266
- }
1267
-
1268
- if (currentBitcoinCashNodeServer == null) {
1269
- final node =
1270
- Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash, useSSL: false);
1271
- await nodeSource.add(node);
1272
- await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
1273
- }
1274
-
1275
- if (currentDogecoinNodeServer == null) {
1276
- final node = Node(uri: dogecoinDefaultNodeUri, type: WalletType.dogecoin, useSSL: true);
1277
- await nodeSource.add(node);
1278
- await sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.key as int);
1279
- }
1280
-
1281
- if (currentPolygonNodeServer == null) {
1282
- final node = Node(uri: polygonDefaultNodeUri, type: WalletType.polygon);
1283
- await nodeSource.add(node);
1284
- await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int);
1285
- }
1286
-
1287
- if (currentBaseNodeServer == null) {
1288
- final node = Node(uri: baseDefaultNodeUri, type: WalletType.base);
1289
- await nodeSource.add(node);
1290
- await sharedPreferences.setInt(PreferencesKey.currentBaseNodeIdKey, node.key as int);
1291
- }
1292
-
1293
- if (currentArbitrumNodeServer == null) {
1294
- final node = Node(uri: arbitrumDefaultNodeUri, type: WalletType.arbitrum);
1295
- await nodeSource.add(node);
1296
- await sharedPreferences.setInt(PreferencesKey.currentArbitrumNodeIdKey, node.key as int);
1297
- }
1298
-
1299
- if (currentBscNodeServer == null) {
1300
- final node = Node(uri: bscDefaultNodeUri, type: WalletType.bsc);
1301
- await nodeSource.add(node);
1302
- await sharedPreferences.setInt(PreferencesKey.currentBscNodeIdKey, node.key as int);
1303
- }
1304
-
1305
- if (currentSolanaNodeServer == null) {
1306
- final node = Node(uri: solanaDefaultNodeUri, type: WalletType.solana);
1307
- await nodeSource.add(node);
1308
- await sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int);
1309
- }
1310
-
1311
- if (currentTronNodeServer == null) {
1312
- final node = Node(uri: tronDefaultNodeUri, type: WalletType.tron);
1313
- await nodeSource.add(node);
1314
- await sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.key as int);
1315
- }
1316
-
1317
- if (currentWowneroNodeServer == null) {
1318
- final node = Node(uri: wowneroDefaultNodeUri, type: WalletType.wownero);
1319
- await nodeSource.add(node);
1320
- await sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.key as int);
1321
- }
1322
-
1323
- if (currentZanoNode == null) {
1324
- final node = Node(uri: zanoDefaultNodeUri, type: WalletType.zano);
1325
- await nodeSource.add(node);
1326
- await sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
1327
- }
1328
-
1329
- if (currentDecredNodeServer == null) {
1330
- final node = Node(uri: decredDefaultUri, type: WalletType.decred);
1331
- await nodeSource.add(node);
1332
- await sharedPreferences.setInt(PreferencesKey.currentDecredNodeIdKey, node.key as int);
1333
- }
1334
-
1335
- if (currentZcashNode == null) {
1336
- final node = Node(uri: zcashDefaultNodeUri, type: WalletType.zcash, useSSL: true);
1337
- await nodeSource.add(node);
1338
- await sharedPreferences.setInt(PreferencesKey.currentZcashNodeIdKey, node.key as int);
1339
- }
1340
-}
1341
-
1342
-Future<void> resetBitcoinElectrumServer(
1343
- Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
1075
+Future<void> resetBitcoinElectrumServer(SharedPreferences sharedPreferences) async {
1076
+ final nodeSource = await Node.getAll();
1077
final currentElectrumSeverId =
1078
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
1346
- final oldElectrumServer = nodeSource.values
1079
+ final oldElectrumServer = nodeSource
1080
.firstWhereOrNull((node) => node.uri.toString().contains('electrumx.cakewallet.com'));
1348
- var cakeWalletNode = nodeSource.values
1081
+ var cakeWalletNode = nodeSource
1082
.firstWhereOrNull((node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
1083
1084
if (cakeWalletNode == null) {
@@ -1357,12 +1090,12 @@ Future<void> resetBitcoinElectrumServer(
1090
// final cakeWalletElectrumTestnet =
1091
// Node(uri: publicBitcoinTestnetElectrumUri, type: WalletType.bitcoin, useSSL: false);
1092
// await nodeSource.add(cakeWalletElectrumTestnet);
1360
- await nodeSource.add(cakeWalletNode);
1093
+ await cakeWalletNode.save();
1094
}
1095
1363
- if (currentElectrumSeverId == oldElectrumServer?.key) {
1096
+ if (currentElectrumSeverId == oldElectrumServer?.id) {
1097
await sharedPreferences.setInt(
1365
- PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletNode.key as int);
1098
+ PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletNode.id);
1099
}
1100
1101
await oldElectrumServer?.delete();
@@ -1380,38 +1113,42 @@ Future<void> migrateExchangeStatus(SharedPreferences sharedPreferences) async {
1113
await sharedPreferences.remove(PreferencesKey.disableExchangeKey);
1114
}
1115
1383
-Future<void> addNanoPowNodeList({required Box<Node> nodes}) async {
1116
+Future<void> addNanoPowNodeList() async {
1117
final nodeList = await loadDefaultNanoPowNodes();
1118
+ final nodes = await Node.getAllPow();
1119
for (var node in nodeList) {
1386
- if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
1387
- await nodes.add(node);
1120
+ if (nodes.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
1121
+ await node.save();
1122
}
1123
}
1124
}
1125
1392
-Node? getNanoDefaultPowNode({required Box<Node> nodes}) {
1393
- return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
1394
- nodes.values.firstWhereOrNull((node) => (node.type == WalletType.nano));
1126
+Future<Node?> getNanoDefaultPowNode() async {
1127
+ final nodes = await Node.getAll();
1128
+ return nodes.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultPowNodeUri) ??
1129
+ nodes.firstWhereOrNull((node) => (node.type == WalletType.nano));
1130
}
1131
1397
-Future<void> addWalletNodeList({required Box<Node> nodes, required WalletType type}) async {
1132
+Future<void> addWalletNodeList({required WalletType type}) async {
1133
+ final nodes = await Node.getAll();
1134
final List<Node> nodeList = await loadDefaultNodes(type);
1135
for (var node in nodeList) {
1400
- if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
1401
- await nodes.add(node);
1136
+ if (nodes.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
1137
+ await node.save();
1138
}
1139
}
1140
}
1141
1142
Future<void> removeMoneroWorld(
1407
- {required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
1143
+ {required SharedPreferences sharedPreferences}) async {
1144
+ final nodes = await Node.getAll();
1145
const cakeWalletMoneroNodeUriPattern = '.moneroworld.com';
1146
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
1410
- final currentMoneroNode = nodes.values.firstWhere((node) => node.key == currentMoneroNodeId);
1147
+ final currentMoneroNode = nodes.firstWhere((node) => node.id == currentMoneroNodeId);
1148
final needToReplaceCurrentMoneroNode =
1149
currentMoneroNode.uri.toString().contains(cakeWalletMoneroNodeUriPattern);
1150
1414
- nodes.values.forEach((node) async {
1151
+ nodes.forEach((node) async {
1152
if (node.type == WalletType.monero &&
1153
node.uri.toString().contains(cakeWalletMoneroNodeUriPattern)) {
1154
await node.delete();
@@ -1420,7 +1157,6 @@ Future<void> removeMoneroWorld(
1157
1158
if (needToReplaceCurrentMoneroNode) {
1159
await _changeDefaultNode(
1423
- nodes: nodes,
1160
sharedPreferences: sharedPreferences,
1161
type: WalletType.monero,
1162
newDefaultUri: newCakeWalletMoneroUri,
@@ -1430,8 +1166,7 @@ Future<void> removeMoneroWorld(
1166
}
1167
}
1168
1433
-Future<void> migrateExistingNodesToUseAutoSwitching(
1434
- {required Box<Node> nodes, required Box<Node> powNodes}) async {
1169
+Future<void> migrateExistingNodesToUseAutoSwitching() async {
1170
final listOfDefaultNodesWithAutoSwitching = [
1171
'bitcoincash.stackwallet.com:50002',
1172
'bch.aftrek.org:50002',
@@ -1465,12 +1200,24 @@ Future<void> migrateExistingNodesToUseAutoSwitching(
1200
'zano.cakewallet.com:11211',
1201
'electrum.cakewallet.com:50002',
1202
];
1468
- for (var node in [...nodes.values.toList(), ...powNodes.values.toList()]) {
1203
+ final nodes = await Node.getAll();
1204
+ for (var node in nodes) {
1205
if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
1206
node.isEnabledForAutoSwitching = true;
1207
await node.save();
1208
}
1209
}
1210
+
1211
+ final powNodes = await Node.getAllPow();
1212
+
1213
+ for(var node in powNodes) {
1214
+ if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
1215
+ node.isEnabledForAutoSwitching = true;
1216
+ node.isPow = true;
1217
+ await node.save();
1218
+ }
1219
+ }
1220
+
1221
}
1222
1223
Future<void> _addXautTokenToExistingEthereumWallets() async {
lib/entities/node_check.dart
new
+69
@@ -0,0 +1,69 @@
1
+import 'package:cake_wallet/core/utilities.dart';
2
+import 'package:cake_wallet/entities/preferences_key.dart';
3
+import 'package:cake_wallet/store/settings_store.dart';
4
+import 'package:cw_core/node.dart';
5
+import 'package:cw_core/node_list.dart';
6
+import 'package:cw_core/wallet_type.dart';
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+const Map<WalletType, String> nodePreferenceKeys = {
10
+ WalletType.monero: PreferencesKey.currentNodeIdKey,
11
+ WalletType.bitcoin: PreferencesKey.currentBitcoinElectrumSererIdKey,
12
+ WalletType.litecoin: PreferencesKey.currentLitecoinElectrumSererIdKey,
13
+ WalletType.haven: PreferencesKey.currentHavenNodeIdKey,
14
+ WalletType.ethereum: PreferencesKey.currentEthereumNodeIdKey,
15
+ WalletType.polygon: PreferencesKey.currentPolygonNodeIdKey,
16
+ WalletType.base: PreferencesKey.currentBaseNodeIdKey,
17
+ WalletType.arbitrum: PreferencesKey.currentArbitrumNodeIdKey,
18
+ WalletType.bsc: PreferencesKey.currentBscNodeIdKey,
19
+ WalletType.nano: PreferencesKey.currentNanoNodeIdKey,
20
+ WalletType.decred: PreferencesKey.currentDecredNodeIdKey,
21
+ WalletType.bitcoinCash: PreferencesKey.currentBitcoinCashNodeIdKey,
22
+ WalletType.dogecoin: PreferencesKey.currentDogecoinNodeIdKey,
23
+ WalletType.solana: PreferencesKey.currentSolanaNodeIdKey,
24
+ WalletType.tron: PreferencesKey.currentTronNodeIdKey,
25
+ WalletType.wownero: PreferencesKey.currentWowneroNodeIdKey,
26
+ WalletType.zano: PreferencesKey.currentZanoNodeIdKey,
27
+ WalletType.zcash: PreferencesKey.currentZcashNodeIdKey,
28
+};
29
+
30
+const Map<WalletType, String> powNodePreferenceKeys = {
31
+ WalletType.nano: PreferencesKey.currentNanoPowNodeIdKey
32
+};
33
+
34
+Future<void> checkNodeForWalletType(SharedPreferences sharedPreferences, SettingsStore settingsStore, WalletType type, bool isPow) async {
35
+ final preferenceKey = isPow ? powNodePreferenceKeys[type] : nodePreferenceKeys[type];
36
+
37
+ if(preferenceKey == null) {
38
+ return;
39
+ }
40
+
41
+ final currentId = await sharedPreferences.getInt(preferenceKey);
42
+
43
+ final nodes = isPow ? await Node.getAllForWalletTypePow(type) : await Node.getAllForWalletType(type);
44
+ final currentNode = nodes.firstWhereOrNull((item)=>item.id == currentId);
45
+
46
+ if(currentNode == null) {
47
+ final newNode = (isPow
48
+ ? await Node.getDefaultPowForWalletType(type)
49
+ : await Node.getDefaultForWalletType(type)) ??
50
+ await getDefaultNodeFromFiles(type, isPow: isPow);
51
+ final newId = await newNode.save();
52
+ sharedPreferences.setInt(preferenceKey, newId);
53
+ settingsStore.nodes[type] = newNode;
54
+ } else {
55
+ settingsStore.nodes[type] = currentNode;
56
+ }
57
+
58
+}
59
+
60
+
61
+Future<void> checkCurrentNodes(SharedPreferences sharedPreferences, SettingsStore settingsStore) async {
62
+ for(final walletType in nodePreferenceKeys.keys) {
63
+ await checkNodeForWalletType(sharedPreferences, settingsStore, walletType, false);
64
+ }
65
+
66
+ for(final walletType in powNodePreferenceKeys.keys) {
67
+ await checkNodeForWalletType(sharedPreferences, settingsStore, walletType, true);
68
+ }
69
+}
\ No newline at end of file
lib/entities/node_list.dart
-148
@@ -1,148 +0,0 @@
1
-import 'package:flutter/services.dart';
2
-import 'package:hive/hive.dart';
3
-import "package:yaml/yaml.dart";
4
-import 'package:cw_core/node.dart';
5
-import 'package:cw_core/wallet_type.dart';
6
-
7
-Future<List<Node>> loadDefaultNodes(WalletType type) async {
8
- String path;
9
- switch (type) {
10
- case WalletType.monero:
11
- path = 'assets/node_list.yml';
12
- break;
13
- case WalletType.bitcoin:
14
- path = 'assets/bitcoin_electrum_server_list.yml';
15
- break;
16
- case WalletType.litecoin:
17
- path = 'assets/litecoin_electrum_server_list.yml';
18
- break;
19
- case WalletType.haven:
20
- path = 'assets/haven_node_list.yml';
21
- break;
22
- // TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
23
- case WalletType.ethereum:
24
- path = 'assets/ethereum_server_list.yml';
25
- break;
26
- case WalletType.nano:
27
- path = 'assets/nano_node_list.yml';
28
- break;
29
- case WalletType.bitcoinCash:
30
- path = 'assets/bitcoin_cash_electrum_server_list.yml';
31
- break;
32
- case WalletType.polygon:
33
- path = 'assets/polygon_node_list.yml';
34
- break;
35
- case WalletType.solana:
36
- path = 'assets/solana_node_list.yml';
37
- break;
38
- case WalletType.tron:
39
- path = 'assets/tron_node_list.yml';
40
- break;
41
- case WalletType.wownero:
42
- path = 'assets/wownero_node_list.yml';
43
- break;
44
- case WalletType.zano:
45
- path = 'assets/zano_node_list.yml';
46
- break;
47
- case WalletType.decred:
48
- path = 'assets/decred_node_list.yml';
49
- break;
50
- case WalletType.dogecoin:
51
- path = 'assets/dogecoin_electrum_server_list.yml';
52
- break;
53
- case WalletType.base:
54
- path = 'assets/base_node_list.yml';
55
- break;
56
- case WalletType.arbitrum:
57
- path = 'assets/arbitrum_node_list.yml';
58
- break;
59
- case WalletType.zcash:
60
- path = 'assets/zcash_node_list.yml';
61
- break;
62
- case WalletType.bsc:
63
- path = 'assets/bsc_node_list.yml';
64
- break;
65
- case WalletType.banano:
66
- case WalletType.none:
67
- path = '';
68
- break;
69
- }
70
-
71
- final nodesRaw = await rootBundle.loadString(path);
72
- final loadedNodes = loadYaml(nodesRaw) as YamlList;
73
- final nodes = <Node>[];
74
-
75
- for (final raw in loadedNodes) {
76
- if (raw is Map) {
77
- final node = Node.fromMap(Map<String, Object>.from(raw));
78
- node.type = type;
79
- nodes.add(node);
80
- }
81
- }
82
-
83
- return nodes;
84
-}
85
-
86
-Future<List<Node>> loadDefaultNanoPowNodes() async {
87
- final powNodesRaw = await rootBundle.loadString('assets/nano_pow_node_list.yml');
88
- final loadedPowNodes = loadYaml(powNodesRaw) as YamlList;
89
- final nodes = <Node>[];
90
-
91
- for (final raw in loadedPowNodes) {
92
- if (raw is Map) {
93
- final node = Node.fromMap(Map<String, Object>.from(raw));
94
- node.type = WalletType.nano;
95
- nodes.add(node);
96
- }
97
- }
98
-
99
- return nodes;
100
-}
101
-
102
-Future<void> resetToDefault(Box<Node> nodeSource) async {
103
- final moneroNodes = await loadDefaultNodes(WalletType.monero);
104
- final bitcoinElectrumServerList = await loadDefaultNodes(WalletType.bitcoin);
105
- final litecoinElectrumServerList = await loadDefaultNodes(WalletType.litecoin);
106
- final bitcoinCashElectrumServerList = await loadDefaultNodes(WalletType.bitcoinCash);
107
- final havenNodes = await loadDefaultNodes(WalletType.haven);
108
- final ethereumNodes = await loadDefaultNodes(WalletType.ethereum);
109
- final nanoNodes = await loadDefaultNodes(WalletType.nano);
110
- final polygonNodes = await loadDefaultNodes(WalletType.polygon);
111
- final solanaNodes = await loadDefaultNodes(WalletType.solana);
112
- final tronNodes = await loadDefaultNodes(WalletType.tron);
113
- final decredNodes = await loadDefaultNodes(WalletType.decred);
114
- final zanoNodes = await loadDefaultNodes(WalletType.zano);
115
- final dogecoinElectrumServerList = await loadDefaultNodes(WalletType.dogecoin);
116
- final baseNodes = await loadDefaultNodes(WalletType.base);
117
- final arbitrumNodes = await loadDefaultNodes(WalletType.arbitrum);
118
- final zcashNodes = await loadDefaultNodes(WalletType.zcash);
119
- final bscNodes = await loadDefaultNodes(WalletType.bsc);
120
-
121
- final nodes = moneroNodes +
122
- bitcoinElectrumServerList +
123
- litecoinElectrumServerList +
124
- havenNodes +
125
- ethereumNodes +
126
- bitcoinCashElectrumServerList +
127
- nanoNodes +
128
- polygonNodes +
129
- solanaNodes +
130
- tronNodes +
131
- zanoNodes +
132
- decredNodes +
133
- dogecoinElectrumServerList +
134
- baseNodes +
135
- arbitrumNodes +
136
- zcashNodes +
137
- bscNodes;
138
-
139
- await nodeSource.clear();
140
- await nodeSource.addAll(nodes);
141
-}
142
-
143
-Future<void> resetPowToDefault(Box<Node> powNodeSource) async {
144
- final nanoPowNodes = await loadDefaultNanoPowNodes();
145
- final nodes = nanoPowNodes;
146
- await powNodeSource.clear();
147
- await powNodeSource.addAll(nodes);
148
-}
lib/main.dart
+7
-16
@@ -16,6 +16,7 @@ import 'package:cake_wallet/entities/default_settings_migration.dart';
16
import 'package:cake_wallet/entities/get_encryption_key.dart';
17
import 'package:cake_wallet/entities/haven_seed_store.dart';
18
import 'package:cake_wallet/entities/language_service.dart';
19
+import 'package:cake_wallet/entities/node_check.dart';
20
import 'package:cake_wallet/entities/template.dart';
21
import 'package:cake_wallet/entities/transaction_description.dart';
22
import 'package:cake_wallet/exchange/exchange_template.dart';
@@ -46,6 +47,7 @@ import 'package:cw_core/hive_type_ids.dart';
47
import 'package:cw_core/key.dart';
48
import 'package:cw_core/mweb_utxo.dart';
49
import 'package:cw_core/node.dart';
50
+import 'package:cw_core/node_legacy.dart' show performNodeHiveMigration;
51
import 'package:cw_core/payjoin_session.dart';
52
import 'package:cw_core/root_dir.dart';
53
import 'package:cw_core/spl_token.dart';
@@ -220,9 +222,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
222
CakeHive.registerAdapter(ContactAdapter());
223
}
224
223
- if (!CakeHive.isAdapterRegistered(Node.typeId)) {
224
- CakeHive.registerAdapter(NodeAdapter());
225
- }
225
226
if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) {
227
CakeHive.registerAdapter(TransactionDescriptionAdapter());
@@ -286,13 +285,12 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
285
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
286
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
287
final contacts = await CakeHive.openBox<Contact>(Contact.boxName);
289
- final nodes = await CakeHive.openBox<Node>(Node.boxName);
290
- final powNodes =
291
- await CakeHive.openBox<Node>(Node.boxName + "pow"); // must be different from Node.boxName
288
final transactionDescriptions = await CakeHive.openBox<TransactionDescription>(
289
TransactionDescription.boxName,
290
encryptionKey: transactionDescriptionsBoxKey);
291
await performTradeHiveMigration(secureStorage);
292
+ await performNodeHiveMigration();
293
+ await validateBuiltinNodes();
294
295
final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
296
final templates = await CakeHive.openBox<Template>(Template.boxName);
@@ -309,8 +307,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
307
await initialSetup(
308
loadWallet: loadWallet,
309
sharedPreferences: await SharedPreferences.getInstance(),
312
- nodes: nodes,
313
- powNodes: powNodes,
310
contactSource: contacts,
311
ordersSource: orders,
312
unspentCoinsInfoSource: unspentCoinsInfoSource,
@@ -322,15 +318,13 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
318
payjoinSessionSource: payjoinSessionSource,
319
anonpayInvoiceInfo: anonpayInvoiceInfo,
320
havenSeedStore: havenSeedStore,
325
- initialMigrationVersion: 65,
321
+ initialMigrationVersion: 66,
322
);
323
}
324
325
Future<void> initialSetup({
326
required bool loadWallet,
327
required SharedPreferences sharedPreferences,
332
- required Box<Node> nodes,
333
- required Box<Node> powNodes,
328
required Box<Contact> contactSource,
329
required Box<Order> ordersSource,
330
// required FiatConvertationService fiatConvertationService,
@@ -350,13 +344,9 @@ Future<void> initialSetup({
344
version: initialMigrationVersion,
345
sharedPreferences: sharedPreferences,
346
contactSource: contactSource,
353
- nodes: nodes,
354
- powNodes: powNodes,
347
havenSeedStore: havenSeedStore,
348
);
349
await setup(
358
- nodeSource: nodes,
359
- powNodeSource: powNodes,
350
contactSource: contactSource,
351
ordersSource: ordersSource,
352
templates: templates,
@@ -368,11 +358,12 @@ Future<void> initialSetup({
358
navigatorKey: navigatorKey,
359
secureStorage: secureStorage,
360
);
361
+ final settingsStore = getIt<SettingsStore>();
362
+ await checkCurrentNodes(sharedPreferences, settingsStore);
363
364
await getIt.get<ResetService>().resetAuthDataOnNewInstall(sharedPreferences);
365
366
await bootstrapOffline();
375
- final settingsStore = getIt<SettingsStore>();
367
if (!settingsStore.currentBuiltinTor) {
368
bootstrapOnline(navigatorKey, loadWallet: loadWallet);
369
}
lib/new-ui/widgets/send_page/send_confirm_sheet.dart
+1
@@ -15,6 +15,7 @@ import 'package:cw_core/crypto_amount_format.dart';
15
import 'package:cw_core/crypto_currency.dart';
16
import 'package:flutter/material.dart';
17
import 'package:flutter_mobx/flutter_mobx.dart';
18
+import 'package:flutter_svg/flutter_svg.dart';
19
import 'package:mobx/mobx.dart';
20
21
class SendConfirmSheet extends StatefulWidget {
lib/src/screens/nodes/node_create_or_edit_page.dart
+5
-4
@@ -128,15 +128,16 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
128
),
129
) ??
130
false;
131
-
131
+
132
if (confirmed) {
133
- await widget.editingNode!.delete();
133
+ await widget.nodeCreateOrEditViewModel.delete(editingNode: widget.editingNode!);
134
Navigator.of(context).pop();
135
}
136
},
137
text: S.of(context).delete,
138
isDisabled: widget.editingNode == null ||
139
!widget.nodeCreateOrEditViewModel.isReady ||
140
+ widget.editingNode!.isBuiltin ||
141
(widget.isSelected ?? false),
142
color: Theme.of(context).colorScheme.errorContainer,
143
textColor: Theme.of(context).colorScheme.onErrorContainer,
@@ -151,9 +152,9 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
152
if (_nodeFormKey.currentState != null && !_nodeFormKey.currentState!.validate()) {
153
return;
154
}
154
-
155
+
156
await widget.nodeCreateOrEditViewModel.save(
156
- editingNode: widget.editingNode, saveAsCurrent: widget.isSelected ?? false);
157
+ saveAsCurrent: widget.isSelected ?? false);
158
if (context.mounted) {
159
Navigator.of(context).pop();
160
}
lib/src/screens/nodes/pow_node_create_or_edit_page.dart
+1
-1
@@ -143,7 +143,7 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
143
}
144
145
await widget.nodeCreateOrEditViewModel.save(
146
- editingNode: widget.editingNode, saveAsCurrent: widget.isSelected ?? false);
146
+ saveAsCurrent: widget.isSelected ?? false);
147
Navigator.of(context).pop();
148
},
149
text: S.of(context).save,
lib/src/screens/nodes/widgets/node_form.dart
+64
-59
@@ -65,66 +65,77 @@ class NodeFormState extends State<NodeForm> {
65
key: _formKey,
66
child: NewListSections(
67
sections: {
68
- 'main': [
69
- ListItemTextField(
70
- keyValue: vm.nodeLabelUIKey,
71
- label: 'Node label',
72
- initialValue: vm.label,
73
- ),
74
- ListItemTextField(
75
- keyValue: vm.nodeAddressUIKey,
76
- label: S.current.node_address,
77
- initialValue: vm.address,
78
- validator: vm.walletType == WalletType.decred
79
- ? NodeAddressValidatorDecredBlankException()
80
- : NodeAddressValidator(),
81
- ),
82
- if (vm.hasPathSupport)
68
+ if(!(vm.editingNode?.isBuiltin ?? false)) ...{
69
+ 'main': [
70
ListItemTextField(
84
- keyValue: vm.nodePathUIKey,
85
- label: '/path',
86
- initialValue: vm.path,
87
- validator: NodePathValidator(),
71
+ keyValue: vm.nodeLabelUIKey,
72
+ label: 'Node label',
73
+ initialValue: vm.label,
74
),
89
- ListItemTextField(
90
- keyValue: vm.nodePortUIKey,
91
- label: S.current.node_port,
92
- initialValue: '',
93
- //keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
94
- validator: NodePortValidator(),
95
- ),
96
- if (vm.hasAuthCredentials) ...[
75
ListItemTextField(
98
- keyValue: vm.nodeUsernameUIKey,
99
- label: S.current.login,
100
- initialValue: vm.login,
76
+ keyValue: vm.nodeAddressUIKey,
77
+ label: S.current.node_address,
78
+ initialValue: vm.address,
79
+ validator: vm.walletType == WalletType.decred
80
+ ? NodeAddressValidatorDecredBlankException()
81
+ : NodeAddressValidator(),
82
),
83
+ if (vm.hasPathSupport)
84
+ ListItemTextField(
85
+ keyValue: vm.nodePathUIKey,
86
+ label: '/path',
87
+ initialValue: vm.path,
88
+ validator: NodePathValidator(),
89
+ ),
90
ListItemTextField(
103
- keyValue: vm.nodePasswordUIKey,
104
- label: S.current.password,
105
- initialValue: vm.password,
91
+ keyValue: vm.nodePortUIKey,
92
+ label: S.current.node_port,
93
+ initialValue: '',
94
+ //keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
95
+ validator: NodePortValidator(),
96
),
107
- ]
108
- ],
109
- 'advanced': [
110
- ListItemCheckbox(
111
- keyValue: vm.useSSLUIKey,
112
- label: S.current.use_ssl,
113
- value: vm.useSSL,
114
- onChanged: (value) => vm.useSSL = value),
115
- ListItemCheckbox(
116
- keyValue: vm.nodeTrustedUIKey,
117
- label: S.current.trusted,
118
- value: vm.trusted,
119
- onChanged: (value) => vm.trusted = value,
120
- ),
121
- if (vm.usesEmbeddedProxy)
97
+ if (vm.hasAuthCredentials) ...[
98
+ ListItemTextField(
99
+ keyValue: vm.nodeUsernameUIKey,
100
+ label: S.current.login,
101
+ initialValue: vm.login,
102
+ ),
103
+ ListItemTextField(
104
+ keyValue: vm.nodePasswordUIKey,
105
+ label: S.current.password,
106
+ initialValue: vm.password,
107
+ ),
108
+ ]
109
+ ],
110
+ 'advanced': [
111
ListItemCheckbox(
123
- keyValue: vm.nodeEmbeddedTorProxyUIKey,
124
- label: 'Embedded Tor SOCKS Proxy',
125
- value: vm.usesEmbeddedProxy,
126
- onChanged: (_) {},
112
+ keyValue: vm.useSSLUIKey,
113
+ label: S.current.use_ssl,
114
+ value: vm.useSSL,
115
+ onChanged: (value) => vm.useSSL = value),
116
+ ListItemCheckbox(
117
+ keyValue: vm.nodeTrustedUIKey,
118
+ label: S.current.trusted,
119
+ value: vm.trusted,
120
+ onChanged: (value) => vm.trusted = value,
121
),
122
+ if (vm.usesEmbeddedProxy)
123
+ ListItemCheckbox(
124
+ keyValue: vm.nodeEmbeddedTorProxyUIKey,
125
+ label: 'Embedded Tor SOCKS Proxy',
126
+ value: vm.usesEmbeddedProxy,
127
+ onChanged: (_) {},
128
+ ),
129
+ if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
130
+ ListItemCheckbox(
131
+ keyValue: vm.autoSwitchingUIKey,
132
+ label: S.current.enable_for_auto_switching,
133
+ value: vm.isEnabledForAutoSwitching,
134
+ onChanged: (value) => vm.isEnabledForAutoSwitching = value),
135
+ ],
136
+ },
137
+
138
+ "proxy" : [
139
ListItemCheckbox(
140
keyValue: vm.useSocksProxyUIKey,
141
label: 'Use SOCKS Proxy',
@@ -141,13 +152,7 @@ class NodeFormState extends State<NodeForm> {
152
initialValue: vm.socksProxyAddress,
153
validator: SocksProxyNodeAddressValidator(),
154
),
144
- if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
145
- ListItemCheckbox(
146
- keyValue: vm.autoSwitchingUIKey,
147
- label: S.current.enable_for_auto_switching,
148
- value: vm.isEnabledForAutoSwitching,
149
- onChanged: (value) => vm.isEnabledForAutoSwitching = value),
150
- ],
155
+ ]
156
},
157
controllers: _controllers,
158
getCheckboxValue: vm.getCheckboxValue,
lib/src/screens/settings/manage_nodes_page.dart
+2
-2
@@ -94,9 +94,9 @@ class ManageNodesPage extends BasePage {
94
nodeListViewModel?.nodes[index] ?? powNodeListViewModel!.nodes[index];
95
late bool isSelected;
96
if (isPow) {
97
- isSelected = node.keyIndex == powNodeListViewModel!.currentNode.keyIndex;
97
+ isSelected = node.id == powNodeListViewModel!.currentNode.id;
98
} else {
99
- isSelected = node.keyIndex == nodeListViewModel!.currentNode.keyIndex;
99
+ isSelected = node.id == nodeListViewModel!.currentNode.id;
100
}
101
final nodeListRow = NodeListRow(
102
title: node.uriRaw,
lib/store/app_store.dart
-3
@@ -14,7 +14,6 @@ import 'package:cw_core/transaction_history.dart';
14
import 'package:cake_wallet/store/wallet_list_store.dart';
15
import 'package:cake_wallet/store/authentication_store.dart';
16
import 'package:cake_wallet/store/settings_store.dart';
17
-import 'package:cake_wallet/store/node_list_store.dart';
17
import 'package:shared_preferences/shared_preferences.dart';
18
19
part 'app_store.g.dart';
@@ -26,7 +25,6 @@ abstract class AppStoreBase with Store {
25
required this.authenticationStore,
26
required this.walletList,
27
required this.settingsStore,
29
- required this.nodeListStore,
28
required this.themeStore,
29
}) : _amountParsingProxy = AmountParsingProxy(settingsStore.displayAmountsInSatoshi) {
30
reaction(
@@ -47,7 +45,6 @@ abstract class AppStoreBase with Store {
45
46
SettingsStore settingsStore;
47
50
- NodeListStore nodeListStore;
48
49
ThemeStore themeStore;
50
lib/store/node_list_store.dart
-34
@@ -1,34 +0,0 @@
1
-import 'dart:async';
2
-import 'package:hive/hive.dart';
3
-import 'package:mobx/mobx.dart';
4
-import 'package:cake_wallet/di.dart';
5
-import 'package:cw_core/node.dart';
6
-import 'package:cake_wallet/utils/mobx.dart';
7
-
8
-part 'node_list_store.g.dart';
9
-
10
-class NodeListStore = NodeListStoreBase with _$NodeListStore;
11
-
12
-abstract class NodeListStoreBase with Store {
13
- NodeListStoreBase() : nodes = ObservableList<Node>();
14
-
15
- static StreamSubscription<BoxEvent>? _onNodesSourceChange;
16
- static NodeListStore? _instance;
17
-
18
- static NodeListStore get instance {
19
- if (_instance != null) {
20
- return _instance!;
21
- }
22
-
23
- final nodeSource = getIt.get<Box<Node>>();
24
- _instance = NodeListStore();
25
- _instance!.nodes.clear();
26
- _instance!.nodes.addAll(nodeSource.values);
27
- _onNodesSourceChange?.cancel();
28
- _onNodesSourceChange = nodeSource.bindToList(_instance!.nodes);
29
-
30
- return _instance!;
31
- }
32
-
33
- final ObservableList<Node> nodes;
34
-}
lib/store/settings_store.dart
+78
-55
@@ -995,7 +995,7 @@ abstract class SettingsStoreBase with Store {
995
996
@observable
997
bool mwebCardDisplay;
998
-
998
+
999
@observable
1000
bool showZcashMissingFundsCard;
1001
@@ -1104,8 +1104,7 @@ abstract class SettingsStoreBase with Store {
1104
_sharedPreferences.setBool(PreferencesKey.shouldShowReceiveWarning, value);
1105
1106
static Future<SettingsStore> load(
1107
- {required Box<Node> nodeSource,
1108
- required Box<Node> powNodeSource,
1107
+ {
1108
required bool isBitcoinBuyEnabled,
1109
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
1110
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance}) async {
@@ -1318,43 +1317,66 @@ abstract class SettingsStoreBase with Store {
1317
final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
1318
final dogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
1319
1320
+
1321
+ final nodeSource = await Node.getAll();
1322
+ final powNodeSource = await Node.getAllPow();
1323
+
1324
/// get the selected node, if null, then use the default
1322
- final moneroNode = nodeSource.get(nodeId) ??
1323
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == newCakeWalletMoneroUri);
1324
- final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId) ??
1325
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == newCakeWalletBitcoinUri);
1326
- final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId) ??
1327
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletLitecoinElectrumUri);
1328
- final ethereumNode = nodeSource.get(ethereumNodeId) ??
1329
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
1330
- final polygonNode = nodeSource.get(polygonNodeId) ??
1331
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
1332
- final baseNode = nodeSource.get(baseNodeId) ??
1333
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == baseDefaultNodeUri);
1334
- final arbitrumNode = nodeSource.get(arbitrumNodeId) ??
1335
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == arbitrumDefaultNodeUri);
1336
- final bscNode = nodeSource.get(bscNodeId) ??
1337
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == bscDefaultNodeUri);
1338
- final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId) ??
1339
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
1340
- final nanoNode = nodeSource.get(nanoNodeId) ??
1341
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
1342
- final decredNode = nodeSource.get(decredNodeId) ??
1343
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
1344
- final nanoPowNode = powNodeSource.get(nanoPowNodeId) ??
1345
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == nanoDefaultPowNodeUri);
1346
- final solanaNode = nodeSource.get(solanaNodeId) ??
1347
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
1348
- final tronNode = nodeSource.get(tronNodeId) ??
1349
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
1350
- final wowneroNode = nodeSource.get(wowneroNodeId) ??
1351
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
1352
- final zanoNode = nodeSource.get(zanoNodeId) ??
1353
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
1354
- final zcashNode = nodeSource.get(zcashNodeId) ??
1355
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == zcashDefaultNodeUri);
1356
- final dogecoinNode = nodeSource.get(dogecoinNodeId) ??
1357
- nodeSource.values.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
1325
+ final moneroNode = nodeSource.firstWhereOrNull((e) => e.id == nodeId) ??
1326
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == newCakeWalletMoneroUri);
1327
+ final bitcoinElectrumServer =
1328
+ nodeSource.firstWhereOrNull((e) => e.id == bitcoinElectrumServerId) ??
1329
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == newCakeWalletBitcoinUri);
1330
+ final litecoinElectrumServer =
1331
+ nodeSource.firstWhereOrNull((e) => e.id == litecoinElectrumServerId) ??
1332
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == cakeWalletLitecoinElectrumUri);
1333
+ final ethereumNode =
1334
+ nodeSource.firstWhereOrNull((e) => e.id == ethereumNodeId) ??
1335
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
1336
+ final polygonNode =
1337
+ nodeSource.firstWhereOrNull((e) => e.id == polygonNodeId) ??
1338
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
1339
+ final baseNode =
1340
+ nodeSource.firstWhereOrNull((e) => e.id == baseNodeId) ??
1341
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == baseDefaultNodeUri);
1342
+ final arbitrumNode =
1343
+ nodeSource.firstWhereOrNull((e) => e.id == arbitrumNodeId) ??
1344
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == arbitrumDefaultNodeUri);
1345
+ final bitcoinCashElectrumServer =
1346
+ nodeSource.firstWhereOrNull((e) => e.id == bitcoinCashElectrumServerId) ??
1347
+ nodeSource.firstWhereOrNull(
1348
+ (e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
1349
+ final nanoNode =
1350
+ nodeSource.firstWhereOrNull((e) => e.id == nanoNodeId) ??
1351
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
1352
+ final decredNode =
1353
+ nodeSource.firstWhereOrNull((e) => e.id == decredNodeId) ??
1354
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
1355
+ final nanoPowNode =
1356
+ powNodeSource.firstWhereOrNull((e) => e.id == nanoPowNodeId) ??
1357
+ powNodeSource.firstWhereOrNull(
1358
+ (e) => e.uriRaw == nanoDefaultPowNodeUri);
1359
+ final solanaNode =
1360
+ nodeSource.firstWhereOrNull((e) => e.id == solanaNodeId) ??
1361
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
1362
+ final tronNode =
1363
+ nodeSource.firstWhereOrNull((e) => e.id == tronNodeId) ??
1364
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
1365
+ final wowneroNode =
1366
+ nodeSource.firstWhereOrNull((e) => e.id == wowneroNodeId) ??
1367
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
1368
+ final zanoNode =
1369
+ nodeSource.firstWhereOrNull((e) => e.id == zanoNodeId) ??
1370
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
1371
+ final dogecoinNode =
1372
+ nodeSource.firstWhereOrNull((e) => e.id == dogecoinNodeId) ??
1373
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
1374
+ final zcashNode =
1375
+ nodeSource.firstWhereOrNull((e) => e.id == zcashNodeId) ??
1376
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == zcashDefaultNodeUri);
1377
+ final bscNode =
1378
+ nodeSource.firstWhereOrNull((e) => e.id == bscNodeId) ??
1379
+ nodeSource.firstWhereOrNull((e) => e.uriRaw == bscDefaultNodeUri);
1380
1381
final packageInfo = await PackageInfo.fromPlatform();
1382
final deviceName = await _getDeviceName() ?? '';
@@ -1572,7 +1594,7 @@ abstract class SettingsStoreBase with Store {
1594
1595
final mwebAdDismissed =
1596
await sharedPreferences.getBool(PreferencesKey.mwebAdDismissed) ?? false;
1575
-
1597
+
1598
final balanceHideCounter = await sharedPreferences.getInt(PreferencesKey.balanceHideCounter) ?? 0;
1599
1600
return SettingsStore(
@@ -2085,20 +2107,21 @@ abstract class SettingsStoreBase with Store {
2107
}
2108
2109
Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
2110
+
2111
switch (walletType) {
2112
case WalletType.bitcoin:
2113
await _sharedPreferences.setInt(
2091
- PreferencesKey.currentBitcoinElectrumSererIdKey, node.key as int);
2114
+ PreferencesKey.currentBitcoinElectrumSererIdKey, node.id);
2115
break;
2116
case WalletType.litecoin:
2117
await _sharedPreferences.setInt(
2095
- PreferencesKey.currentLitecoinElectrumSererIdKey, node.key as int);
2118
+ PreferencesKey.currentLitecoinElectrumSererIdKey, node.id);
2119
break;
2120
case WalletType.monero:
2098
- await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, node.key as int);
2121
+ await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, node.id);
2122
break;
2123
case WalletType.haven:
2101
- await _sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.key as int);
2124
+ await _sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.id);
2125
break;
2126
case WalletType.ethereum:
2127
case WalletType.polygon:
@@ -2107,36 +2130,36 @@ abstract class SettingsStoreBase with Store {
2130
case WalletType.bsc:
2131
final chainId = evm!.getChainIdByWalletType(node.type);
2132
final preferenceKey = _getEVMNodePreferenceKey(chainId);
2110
- await _sharedPreferences.setInt(preferenceKey, node.key as int);
2133
+ await _sharedPreferences.setInt(preferenceKey, node.id);
2134
nodes[node.type] = node;
2135
break;
2136
case WalletType.bitcoinCash:
2137
await _sharedPreferences.setInt(
2115
- PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
2138
+ PreferencesKey.currentBitcoinCashNodeIdKey, node.id);
2139
break;
2140
case WalletType.nano:
2118
- await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
2141
+ await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.id);
2142
break;
2143
case WalletType.solana:
2121
- await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int);
2144
+ await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.id);
2145
break;
2146
case WalletType.tron:
2124
- await _sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.key as int);
2147
+ await _sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.id);
2148
break;
2149
case WalletType.wownero:
2127
- await _sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.key as int);
2150
+ await _sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.id);
2151
break;
2152
case WalletType.decred:
2130
- await _sharedPreferences.setInt(PreferencesKey.currentDecredNodeIdKey, node.key as int);
2153
+ await _sharedPreferences.setInt(PreferencesKey.currentDecredNodeIdKey, node.id);
2154
break;
2155
case WalletType.zano:
2133
- await _sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
2156
+ await _sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.id);
2157
break;
2158
case WalletType.dogecoin:
2136
- await _sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.key as int);
2159
+ await _sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.id);
2160
break;
2161
case WalletType.zcash:
2139
- await _sharedPreferences.setInt(PreferencesKey.currentZcashNodeIdKey, node.key as int);
2162
+ await _sharedPreferences.setInt(PreferencesKey.currentZcashNodeIdKey, node.id);
2163
break;
2164
case WalletType.none:
2165
throw UnimplementedError();
@@ -2150,7 +2173,7 @@ abstract class SettingsStoreBase with Store {
2173
Future<void> _saveCurrentPowNode(Node node, WalletType walletType) async {
2174
switch (walletType) {
2175
case WalletType.nano:
2153
- await _sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.key as int);
2176
+ await _sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.id);
2177
break;
2178
default:
2179
break;
lib/utils/exception_handler.dart
+8
-13
@@ -117,7 +117,7 @@ class ExceptionHandler {
117
if (await onLedgerError(errorDetails)) return;
118
119
if (kDebugMode || kProfileMode) {
120
- if (_ignoreError(errorDetails.exception.toString()) ||
120
+ if(_ignoreError(errorDetails.exception.toString()) ||
121
_ignoreError(errorDetails.stack.toString())) {
122
printV("(BELOW ERROR IS IGNORED AND WILL NOT TRIGGER POPUP IN PROD)");
123
}
@@ -127,8 +127,7 @@ class ExceptionHandler {
127
}
128
129
if (_ignoreError(errorDetails.exception.toString()) ||
130
- _ignoreError(errorDetails.stack.toString()) ||
131
- _flutterErrorIgnore(errorDetails)) {
130
+ _ignoreError(errorDetails.stack.toString())) {
131
return;
132
}
133
@@ -216,7 +215,8 @@ class ExceptionHandler {
215
return S.current.ledger_error_tx_rejected_by_user;
216
} else if (errorCode.contains("5515")) {
217
return S.current.ledger_error_device_locked;
219
- } else if (["6e01", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
218
+ } else
219
+ if (["6e01", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
220
return S.current.ledger_error_wrong_app;
221
}
222
return null;
@@ -229,8 +229,9 @@ class ExceptionHandler {
229
context: navigatorKey.currentContext!,
230
builder: (context) => AlertWithOneAction(
231
alertTitle: "Ledger Error",
232
- alertContent: interpretErrorCode(errorDetails.exception.toString()) ??
233
- S.of(context).ledger_connection_error,
232
+ alertContent:
233
+ interpretErrorCode(errorDetails.exception.toString()) ??
234
+ S.of(context).ledger_connection_error,
235
buttonText: S.of(context).close,
236
buttonAction: () => Navigator.of(context).pop(),
237
),
@@ -295,7 +296,7 @@ class ExceptionHandler {
296
"Wallet is null",
297
"Wrong Device Status: 0x5515 (UNKNOWN)",
298
"Command handling failed. With error: hostUnreachable",
298
-
299
+
300
"FocusScopeNode was used after being disposed",
301
"_getDismissibleFlushbar",
302
"_QueuedFuture.execute (package:universal_ble/src/queue.dart:65)",
@@ -438,10 +439,4 @@ class ExceptionHandler {
439
440
_hasError = false;
441
}
441
-
442
- static bool _flutterErrorIgnore(FlutterErrorDetails errorDetails) {
443
- // most probably a flutter context error so just ignore it if there is no stack we can debug with
444
- return errorDetails.exception.toString().contains("Null check operator used on a null value") &&
445
- errorDetails.stack == null;
446
- }
442
}
lib/view_model/node_list/node_create_or_edit_view_model.dart
+46
-36
@@ -5,10 +5,11 @@ import 'package:cake_wallet/store/settings_store.dart';
5
import 'package:cake_wallet/utils/permission_handler.dart';
6
import 'package:collection/collection.dart';
7
import 'package:cw_core/node.dart';
8
+import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
9
+import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
10
import 'package:cw_core/utils/proxy_wrapper.dart';
11
import 'package:cw_core/wallet_type.dart';
12
import 'package:flutter/cupertino.dart';
11
-import 'package:hive/hive.dart';
13
import 'package:mobx/mobx.dart';
14
import 'package:permission_handler/permission_handler.dart';
15
@@ -19,7 +20,7 @@ class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase
20
21
abstract class NodeCreateOrEditViewModelBase with Store {
22
NodeCreateOrEditViewModelBase(
22
- this._nodeSource, this.walletType, this.editingNode, this._settingsStore)
23
+ this.isPow, this.nodeListViewModel,this.powNodeListViewModel, this.walletType, this._settingsStore, {this.editingNode})
24
: state = InitialExecutionState(),
25
connectionState = InitialExecutionState(),
26
label = editingNode?.label ?? '',
@@ -36,8 +37,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
37
editingNode?.isEnabledForAutoSwitching ?? false,
38
useSocksProxy = editingNode?.socksProxyAddress != null &&
39
editingNode!.socksProxyAddress!.isNotEmpty,
39
- useSSL = editingNode?.useSSL ?? false {
40
- }
40
+ useSSL = editingNode?.useSSL ?? false {}
41
42
final nodeLabelUIKey = 'node_label_row_key';
43
final nodeAddressUIKey = 'node_address_row_key';
@@ -110,6 +110,15 @@ abstract class NodeCreateOrEditViewModelBase with Store {
110
@observable
111
String socksProxyAddress;
112
113
+ @observable
114
+ Node? editingNode;
115
+
116
+ @observable
117
+ bool isPow;
118
+
119
+ final NodeListViewModel? nodeListViewModel;
120
+ final PowNodeListViewModel? powNodeListViewModel;
121
+
122
@computed
123
bool get isReady =>
124
(address.isNotEmpty) ||
@@ -158,8 +167,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
167
}
168
169
final WalletType walletType;
161
- final Node? editingNode;
162
- final Box<Node> _nodeSource;
170
final SettingsStore _settingsStore;
171
172
void updateViewModelFromText(String key, String value) {
@@ -248,33 +255,45 @@ abstract class NodeCreateOrEditViewModelBase with Store {
255
void setSocksProxyAddress(String val) => socksProxyAddress = val;
256
257
@action
251
- Future<void> save({Node? editingNode, bool saveAsCurrent = false}) async {
252
- final node = Node(
253
- label: label,
254
- uri: uri,
255
- path: path,
256
- type: walletType,
257
- login: login,
258
- password: password,
259
- useSSL: useSSL,
260
- trusted: trusted,
261
- isEnabledForAutoSwitching: isEnabledForAutoSwitching,
262
- socksProxyAddress: socksProxyAddress);
258
+ Future<void> delete({required Node editingNode}) async {
259
+ await editingNode.delete();
260
+ if(nodeListViewModel != null) {
261
+ nodeListViewModel!.bindNodes();
262
+ }
263
+ if(powNodeListViewModel != null) {
264
+ powNodeListViewModel!.bindNodes();
265
+ }
266
+ }
267
+
268
+ @action
269
+ Future<void> save({bool saveAsCurrent = false}) async {
270
+ editingNode ??= Node();
271
+ editingNode!.type = walletType;
272
+ editingNode!.label = label;
273
+ editingNode!.uriRaw = uri;
274
+ editingNode!.path = path;
275
+ editingNode!.login = login;
276
+ editingNode!.password = password;
277
+ editingNode!.isPow = isPow;
278
+ editingNode!.useSSL = useSSL;
279
+ editingNode!.trusted = trusted;
280
+ editingNode!.socksProxyAddress = socksProxyAddress;
281
+
282
try {
283
state = IsExecutingState();
265
- if (editingNode != null) {
266
- await _nodeSource.put(editingNode.key, node);
267
- } else if (_existingNode(node) != null) {
268
- setAsCurrent(_existingNode(node)!);
269
- } else {
270
- await _nodeSource.add(node);
271
- setAsCurrent(_nodeSource.values.last);
272
- }
284
+ await editingNode!.save();
285
if (saveAsCurrent) {
274
- setAsCurrent(node);
286
+ setAsCurrent(editingNode!);
287
}
288
289
state = ExecutedSuccessfullyState();
290
+ if(nodeListViewModel != null) {
291
+ nodeListViewModel!.bindNodes();
292
+ }
293
+ if(powNodeListViewModel != null) {
294
+ powNodeListViewModel!.bindNodes();
295
+ }
296
+
297
} catch (e) {
298
state = FailureState(e.toString());
299
}
@@ -301,15 +320,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
320
}
321
}
322
304
- Node? _existingNode(Node node) {
305
- final nodes = _nodeSource.values.toList();
306
- nodes.forEach((item) {
307
- item.login ??= '';
308
- item.password ??= '';
309
- item.useSSL ??= false;
310
- });
311
- return nodes.firstWhereOrNull((item) => item == node);
312
- }
323
324
@action
325
void setAsCurrent(Node node) => _settingsStore.nodes[walletType] = node;
lib/view_model/node_list/node_list_view_model.dart
+15
-22
@@ -1,8 +1,7 @@
1
import 'package:cake_wallet/generated/i18n.dart';
2
import 'package:cake_wallet/store/app_store.dart';
3
-import 'package:cake_wallet/utils/mobx.dart';
3
+import 'package:cw_core/node_list.dart';
4
import 'package:cw_core/utils/proxy_wrapper.dart';
5
-import 'package:hive/hive.dart';
5
import 'package:mobx/mobx.dart';
6
import 'package:cw_core/wallet_base.dart';
7
import 'package:cake_wallet/store/settings_store.dart';
@@ -18,13 +17,13 @@ part 'node_list_view_model.g.dart';
17
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
18
19
abstract class NodeListViewModelBase with Store {
21
- NodeListViewModelBase(this._nodeSource, this._appStore)
20
+ NodeListViewModelBase(this._appStore)
21
: nodes = ObservableList<Node>(),
22
settingsStore = _appStore.settingsStore {
24
- _bindNodes();
23
+ bindNodes();
24
25
reaction((_) => _appStore.wallet, (WalletBase? _wallet) {
27
- _bindNodes();
26
+ bindNodes();
27
});
28
29
reaction((_) {
@@ -35,7 +34,7 @@ abstract class NodeListViewModelBase with Store {
34
}
35
return null;
36
}, (_) {
38
- _bindNodes();
37
+ bindNodes();
38
});
39
}
40
@@ -73,24 +72,24 @@ abstract class NodeListViewModelBase with Store {
72
73
final ObservableList<Node> nodes;
74
final SettingsStore settingsStore;
76
- final Box<Node> _nodeSource;
75
final AppStore _appStore;
76
77
Future<void> reset() async {
80
- await resetToDefault(_nodeSource);
78
+ await resetToDefault();
79
80
final wallet = _appStore.wallet!;
81
final walletType = wallet.type;
82
83
Node node;
84
if (walletType == WalletType.bitcoin && wallet.isTestnet) {
87
- node = getBitcoinTestnetDefaultElectrumServer(nodes: _nodeSource)!;
85
+ node = (await getBitcoinTestnetDefaultElectrumServer())!;
86
+
87
} else if (isEVMCompatibleChain(walletType)) {
88
final chainId = evm!.getSelectedChainId(wallet);
89
if (chainId != null) {
90
final nodeWalletType = evm!.getWalletTypeByChainId(chainId);
91
if (nodeWalletType != null) {
93
- node = getDefaultNode(nodes: _nodeSource, type: nodeWalletType)!;
92
+ node = (await Node.getDefaultForWalletType(nodeWalletType))!;
93
} else {
94
throw Exception(
95
'Cannot reset node for EVM wallet: wallet type not found for chainId: $chainId');
@@ -99,7 +98,7 @@ abstract class NodeListViewModelBase with Store {
98
throw Exception('Cannot reset node for EVM wallet: chainId is null');
99
}
100
} else {
102
- node = getDefaultNode(nodes: _nodeSource, type: walletType)!;
101
+ node = (await Node.getDefaultForWalletType(_appStore.wallet!.type))!;
102
}
103
104
await setAsCurrent(node);
@@ -130,7 +129,7 @@ abstract class NodeListViewModelBase with Store {
129
}
130
131
@action
133
- void _bindNodes() {
132
+ Future<void> bindNodes() async {
133
nodes.clear();
134
final wallet = _appStore.wallet!;
135
final walletType = wallet.type;
@@ -141,11 +140,8 @@ abstract class NodeListViewModelBase with Store {
140
if (chainId != null) {
141
final nodeWalletType = evm!.getWalletTypeByChainId(chainId);
142
if (nodeWalletType != null) {
144
- _nodeSource.bindToList(
145
- nodes,
146
- filter: (val) => val.type == nodeWalletType,
147
- initialFire: true,
148
- );
143
+ nodes.addAll(await Node.getAllForWalletType(nodeWalletType));
144
+
145
return;
146
}
147
}
@@ -154,10 +150,7 @@ abstract class NodeListViewModelBase with Store {
150
}
151
152
// For non-EVM wallets, use the wallet type directly
157
- _nodeSource.bindToList(
158
- nodes,
159
- filter: (val) => val.type == walletType,
160
- initialFire: true,
161
- );
153
+ nodes.addAll(await Node.getAllForWalletType(walletType));
154
+
155
}
156
}
lib/view_model/node_list/pow_node_list_view_model.dart
+8
-12
@@ -1,6 +1,7 @@
1
import 'package:cake_wallet/generated/i18n.dart';
2
import 'package:cake_wallet/store/app_store.dart';
3
import 'package:cake_wallet/utils/mobx.dart';
4
+import 'package:cw_core/node_list.dart';
5
import 'package:cw_core/utils/proxy_wrapper.dart';
6
import 'package:hive/hive.dart';
7
import 'package:mobx/mobx.dart';
@@ -16,13 +17,13 @@ part 'pow_node_list_view_model.g.dart';
17
class PowNodeListViewModel = PowNodeListViewModelBase with _$PowNodeListViewModel;
18
19
abstract class PowNodeListViewModelBase with Store {
19
- PowNodeListViewModelBase(this._nodeSource, this._appStore)
20
+ PowNodeListViewModelBase(this._appStore)
21
: nodes = ObservableList<Node>(),
22
settingsStore = _appStore.settingsStore {
22
- _bindNodes();
23
+ bindNodes();
24
25
reaction((_) => _appStore.wallet, (WalletBase? _wallet) {
25
- _bindNodes();
26
+ bindNodes();
27
});
28
}
29
@@ -50,17 +51,16 @@ abstract class PowNodeListViewModelBase with Store {
51
52
final ObservableList<Node> nodes;
53
final SettingsStore settingsStore;
53
- final Box<Node> _nodeSource;
54
final AppStore _appStore;
55
56
Future<void> reset() async {
57
- await resetPowToDefault(_nodeSource);
57
+ await resetPowToDefault();
58
59
Node node;
60
61
switch (_appStore.wallet!.type) {
62
case WalletType.nano:
63
- node = getNanoDefaultPowNode(nodes: _nodeSource)!;
63
+ node = (await getNanoDefaultPowNode())!;
64
break;
65
default:
66
throw Exception('Unexpected wallet type: ${_appStore.wallet!.type} for pow node list');
@@ -76,12 +76,8 @@ abstract class PowNodeListViewModelBase with Store {
76
settingsStore.powNodes[_appStore.wallet!.type] = node;
77
78
@action
79
- void _bindNodes() {
79
+ Future<void> bindNodes() async {
80
nodes.clear();
81
- _nodeSource.bindToList(
82
- nodes,
83
- filter: (val) => val.type == _appStore.wallet!.type,
84
- initialFire: true,
85
- );
81
+ nodes.addAll(await Node.getAllPow());
82
}
83
}
lib/view_model/restore_from_backup_view_model.dart
+1
-1
@@ -62,7 +62,7 @@ abstract class RestoreFromBackupViewModelBase with Store {
62
63
final store = getIt.get<AppStore>();
64
ReactionDisposer? reaction;
65
- await store.settingsStore.reload(nodeSource: getIt.get<Box<Node>>());
65
+ //await store.settingsStore.reload(nodeSource: getIt.get<Box<Node>>());
66
await store.themeStore.loadSavedTheme(isFromBackup: true);
67
reaction = autorun((_) {
68
final wallet = store.wallet;
res/values/strings_ar.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "هل أموالك مفقودة؟",
1378
"zcash_card_scan": "مسح",
1379
"zcash_card_warning": "لا تُغلق التطبيق حتى يكتمل الإجراء، لأنك إن فعلت ذلك فستحتاج هذه العملية إلى البدء من جديد من البداية."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_bg.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Липсват средства?",
1378
"zcash_card_scan": "Сканирай",
1379
"zcash_card_warning": "Не затваряйте приложението, докато процедурата не приключи. Ако го направите, процесът ще трябва да започне отначало."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_cs.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Chybějící prostředky?",
1378
"zcash_card_scan": "Skenovat",
1379
"zcash_card_warning": "Nezavírejte aplikaci, dokud se postup nedokončí. Pokud tak učiníte, bude nutné tento proces spustit znovu od začátku."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_de.arb
+1
-1
@@ -1381,4 +1381,4 @@
1381
"zcash_card_missing_funds": "Fehlende Gelder?",
1382
"zcash_card_scan": "Scannen",
1383
"zcash_card_warning": "Schließen Sie die App nicht, bis der Vorgang abgeschlossen ist. Andernfalls muss der Vorgang von Grund auf neu gestartet werden."
1384
-}
\ No newline at end of file
1384
+}
res/values/strings_es.arb
+1
-1
@@ -1379,4 +1379,4 @@
1379
"zcash_card_missing_funds": "¿Faltan fondos?",
1380
"zcash_card_scan": "Escanear",
1381
"zcash_card_warning": "No cierre la aplicación hasta que se complete el procedimiento; si lo hace, este proceso deberá reiniciarse desde cero."
1382
-}
\ No newline at end of file
1382
+}
res/values/strings_fa.arb
+1
-1
@@ -1374,4 +1374,4 @@
1374
"zcash_card_missing_funds": "موجودی گم شده؟",
1375
"zcash_card_scan": "اسکن",
1376
"zcash_card_warning": "تا زمانی که این فرایند کامل نشده است، برنامه را نبندید؛ در غیر این صورت، این فرایند باید از ابتدا دوباره شروع شود."
1377
-}
\ No newline at end of file
1377
+}
res/values/strings_fr.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Fonds manquants ?",
1378
"zcash_card_scan": "Scanner",
1379
"zcash_card_warning": "Ne fermez pas l'application tant que la procédure n'est pas terminée. Si vous le faites, ce processus devra redémarrer depuis le début."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_gn.arb
+1
-1
@@ -1116,4 +1116,4 @@
1116
"zcash_card_missing_funds": "¿Nde fondo okañy?",
1117
"zcash_card_scan": "Escanear",
1118
"zcash_card_warning": "Ani remboty pe app pe procedimiento opa hag̃ua, rejapo ramo upéicha ko proceso tekotevẽta oñepyrũ jey cero guive."
1119
-}
\ No newline at end of file
1119
+}
res/values/strings_ha.arb
+1
-1
@@ -1380,4 +1380,4 @@
1380
"zcash_card_missing_funds": "Kuɗi sun ɓace?",
1381
"zcash_card_scan": "Duba",
1382
"zcash_card_warning": "Kada ku rufe manhajar har sai an kammala aikin; idan kun yi haka, wannan tsari zai buƙaci a sake farawa daga farko."
1383
-}
\ No newline at end of file
1383
+}
res/values/strings_hi.arb
+2
-2
@@ -736,8 +736,8 @@
736
"payjoin_unavailable_sheet_title": "Payjoin उपलब्ध क्यों नहीं है?",
737
"payment_id": "भुगतान आईडी: ",
738
"payment_made_easy": "भुगतान करना आसान",
739
- "payment_was_received": "आपका भुगतान प्राप्त हो गया।",
739
"Payment_was_received": "आपका भुगतान प्राप्त हो गया था।",
740
+ "payment_was_received": "आपका भुगतान प्राप्त हो गया।",
741
"payments": "भुगतान",
742
"pending": " (लंबित)",
743
"percentageOf": "${amount} का",
@@ -1379,4 +1379,4 @@
1379
"zcash_card_missing_funds": "फंड गायब हैं?",
1380
"zcash_card_scan": "स्कैन",
1381
"zcash_card_warning": "प्रक्रिया पूरी होने तक ऐप बंद न करें। यदि आप ऐसा करते हैं, तो यह प्रक्रिया शुरू से फिर से शुरू करनी होगी।"
1382
-}
\ No newline at end of file
1382
+}
res/values/strings_hr.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Nedostaju sredstva?",
1378
"zcash_card_scan": "Skeniraj",
1379
"zcash_card_warning": "Ne zatvarajte aplikaciju dok se postupak ne dovrši; ako to učinite, postupak će se morati ponovno pokrenuti ispočetka."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_hy.arb
+1
-1
@@ -1375,4 +1375,4 @@
1375
"zcash_card_missing_funds": "Միջոցները բացակա՞յում են",
1376
"zcash_card_scan": "Սկանավորել",
1377
"zcash_card_warning": "Մի փակեք հավելվածը մինչև ընթացակարգի ավարտը, քանի որ հակառակ դեպքում այս գործընթացը պետք է վերագործարկվի զրոյից։"
1378
-}
\ No newline at end of file
1378
+}
res/values/strings_id.arb
+1
-1
@@ -1380,4 +1380,4 @@
1380
"zcash_card_missing_funds": "Dana hilang?",
1381
"zcash_card_scan": "Pindai",
1382
"zcash_card_warning": "Jangan tutup aplikasi sampai prosedur selesai. Jika Anda melakukannya, proses ini harus dimulai ulang dari awal."
1383
-}
\ No newline at end of file
1383
+}
res/values/strings_it.arb
+1
-1
@@ -1379,4 +1379,4 @@
1379
"zcash_card_missing_funds": "Fondi mancanti?",
1380
"zcash_card_scan": "Scansiona",
1381
"zcash_card_warning": "Non chiudere l'app finché la procedura non è completata, altrimenti sarà necessario riavviare il processo da zero."
1382
-}
\ No newline at end of file
1382
+}
res/values/strings_ja.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "資金が見当たりませんか?",
1378
"zcash_card_scan": "スキャン",
1379
"zcash_card_warning": "手順が完了するまでアプリを閉じないでください。閉じると、このプロセスを最初からやり直す必要があります。"
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_ko.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "자금이 사라졌나요?",
1378
"zcash_card_scan": "스캔",
1379
"zcash_card_warning": "절차가 완료될 때까지 앱을 닫지 마십시오. 닫으면 이 과정을 처음부터 다시 시작해야 합니다."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_my.arb
+1
-1
@@ -1376,4 +1376,4 @@
1376
"zcash_card_missing_funds": "ငွေကြေး ပျောက်ဆုံးနေပါသလား?",
1377
"zcash_card_scan": "စကင်",
1378
"zcash_card_warning": "လုပ်ငန်းစဉ် ပြီးဆုံးသည်အထိ အက်ပ်ကို မပိတ်ပါနှင့်။ ပိတ်လိုက်ပါက ဤလုပ်ငန်းစဉ်ကို အစမှ ပြန်လည်စတင်ရမည်ဖြစ်သည်။"
1379
-}
\ No newline at end of file
1379
+}
res/values/strings_nl.arb
+1
-1
@@ -1374,4 +1374,4 @@
1374
"zcash_card_missing_funds": "Fondsen ontbreken?",
1375
"zcash_card_scan": "Scannen",
1376
"zcash_card_warning": "Sluit de app niet voordat de procedure is voltooid. Als je dit wel doet, moet dit proces helemaal opnieuw worden gestart."
1377
-}
\ No newline at end of file
1377
+}
res/values/strings_pl.arb
+1
-1
@@ -1375,4 +1375,4 @@
1375
"zcash_card_missing_funds": "Brakuje środków?",
1376
"zcash_card_scan": "Skanuj",
1377
"zcash_card_warning": "Nie zamykaj aplikacji do czasu zakończenia procedury. Jeśli to zrobisz, proces będzie musiał rozpocząć się od nowa."
1378
-}
\ No newline at end of file
1378
+}
res/values/strings_pt.arb
+1
-1
@@ -1379,4 +1379,4 @@
1379
"zcash_card_missing_funds": "Fundos em falta?",
1380
"zcash_card_scan": "Escanear",
1381
"zcash_card_warning": "Não feche o aplicativo até que o procedimento seja concluído; se você fizer isso, esse processo precisará ser reiniciado do zero."
1382
-}
\ No newline at end of file
1382
+}
res/values/strings_ru.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Не хватает средств?",
1378
"zcash_card_scan": "Сканировать",
1379
"zcash_card_warning": "Не закрывайте приложение до завершения процедуры. Если вы это сделаете, процесс придется перезапустить с нуля."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_th.arb
+1
-1
@@ -1376,4 +1376,4 @@
1376
"zcash_card_missing_funds": "ยอดเงินหายไป?",
1377
"zcash_card_scan": "สแกน",
1378
"zcash_card_warning": "อย่าปิดแอปจนกว่าขั้นตอนจะเสร็จสิ้น หากคุณปิดแอป กระบวนการนี้จะต้องเริ่มใหม่ตั้งแต่ต้น"
1379
-}
\ No newline at end of file
1379
+}
res/values/strings_tl.arb
+1
-1
@@ -1376,4 +1376,4 @@
1376
"zcash_card_missing_funds": "Nawawalang pondo?",
1377
"zcash_card_scan": "I-scan",
1378
"zcash_card_warning": "Huwag isara ang app hanggang sa makumpleto ang proseso; kung gagawin mo ito, kakailanganing magsimula muli mula sa simula."
1379
-}
\ No newline at end of file
1379
+}
res/values/strings_tr.arb
+1
-1
@@ -1376,4 +1376,4 @@
1376
"zcash_card_missing_funds": "Bakiye eksik mi?",
1377
"zcash_card_scan": "Tara",
1378
"zcash_card_warning": "İşlem tamamlanana kadar uygulamayı kapatmayın; aksi takdirde bu işlemin baştan yeniden başlatılması gerekecektir."
1379
-}
\ No newline at end of file
1379
+}
res/values/strings_uk.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Зникли кошти?",
1378
"zcash_card_scan": "Сканувати",
1379
"zcash_card_warning": "Не закривайте застосунок, доки процедура не завершиться. Якщо ви це зробите, цей процес потрібно буде перезапустити з нуля."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_ur.arb
+1
-1
@@ -1378,4 +1378,4 @@
1378
"zcash_card_missing_funds": "فنڈز غائب ہیں؟",
1379
"zcash_card_scan": "اسکین کریں",
1380
"zcash_card_warning": "طریقہ کار مکمل ہونے تک ایپ بند نہ کریں۔ اگر آپ ایسا کریں گے تو یہ عمل شروع سے دوبارہ شروع کرنا پڑے گا۔"
1381
-}
\ No newline at end of file
1381
+}
res/values/strings_vi.arb
+1
-1
@@ -1373,4 +1373,4 @@
1373
"zcash_card_missing_funds": "Thiếu tiền?",
1374
"zcash_card_scan": "Quét",
1375
"zcash_card_warning": "Không đóng ứng dụng cho đến khi quy trình hoàn tất; nếu bạn làm vậy, quy trình này sẽ phải bắt đầu lại từ đầu."
1376
-}
\ No newline at end of file
1376
+}
res/values/strings_yo.arb
+1
-1
@@ -1377,4 +1377,4 @@
1377
"zcash_card_missing_funds": "Ṣe owó rẹ sọnù?",
1378
"zcash_card_scan": "Ṣàwárí",
1379
"zcash_card_warning": "Maṣe pa ohun elo naa titi ilana naa yoo fi pari; bí o bá ṣe bẹ́ẹ̀, ilana yìí yóò ní láti tún bẹ̀rẹ̀ láti ìbẹ̀rẹ̀."
1380
-}
\ No newline at end of file
1380
+}
res/values/strings_zh.arb
+1
-1
@@ -1376,4 +1376,4 @@
1376
"zcash_card_missing_funds": "资金不见了?",
1377
"zcash_card_scan": "扫描",
1378
"zcash_card_warning": "在该过程完成之前请勿关闭应用程序,否则该过程将需要从头重新开始。"
1379
-}
\ No newline at end of file
1379
+}