From 52468989681f5cdd97133ce77120af48a8a2c77d Mon Sep 17 00:00:00 2001 From: DanS Date: Fri, 2 Oct 2026 20:08:14 -0500 Subject: [PATCH] feat(ui): treat transparent addresses as mining-only addresses DragonX is a private chain (-ac_private=1): consensus rejects any non-coinbase output to a transparent address, so a t-address can only ever receive mining rewards, and its coins can only move to a shielded address. The wallet treated them like ordinary recipients. Block paying one: - Send: a transparent recipient shows "Mining address - can't be paid" and disables Review Send (tooltip explains; ask for a zs... address). Typing, paste, contacts and payment URIs all go through this field. - Overview drag-to-transfer: a mining-address row is never a transfer target (it only reorders). - Pool payout must be shielded (pools pay with ordinary transactions): field tooltip, disabled Start button and the start check say why. - isValidRecipientAddress() is now shielded-only; new isDragonXAddress() and classifyRecipient() (Shielded / MiningOnly / Invalid). Call them mining addresses: - Overview: "Mining rewards" card (amber "Not yet shielded" when there is a balance; hover explains; click opens the Shield dialog), "New mining address" button with a tooltip, rows typed "Mining". - QR / label dialogs, portfolio filter, contact badge ("Mining only"), Receive notifications. i18n: 17 new keys in all 8 languages, 12 dead keys removed, CJK subset rebuilt. Tests: recipient classification, translation completeness. UI sweep: new "send-mining-recipient" target. Co-Authored-By: Claude Opus 5.5 --- res/fonts/NotoSansCJK-Subset.ttf | Bin 763744 -> 765100 bytes res/lang/de.json | 29 +++-- res/lang/es.json | 29 +++-- res/lang/fr.json | 29 +++-- res/lang/ja.json | 29 +++-- res/lang/ko.json | 29 +++-- res/lang/pt.json | 29 +++-- res/lang/ru.json | 29 +++-- res/lang/zh.json | 29 +++-- scripts/add_missing_translations.py | 170 ++++++++++++++++++++++++++ src/app_network.cpp | 6 +- src/app_sweep.cpp | 5 + src/ui/windows/address_label_dialog.h | 2 +- src/ui/windows/balance_components.cpp | 14 ++- src/ui/windows/balance_tab.cpp | 37 +++--- src/ui/windows/contacts_tab.cpp | 2 +- src/ui/windows/market_tab.cpp | 2 +- src/ui/windows/mining_controls.cpp | 4 +- src/ui/windows/mining_mode_toggle.cpp | 5 +- src/ui/windows/receive_tab.cpp | 4 +- src/ui/windows/send_tab.cpp | 25 +++- src/ui/windows/send_tab.h | 2 + src/util/address_validation.cpp | 14 ++- src/util/address_validation.h | 12 +- src/util/i18n.cpp | 29 +++-- tests/test_phase4.cpp | 65 +++++++--- 26 files changed, 468 insertions(+), 162 deletions(-) diff --git a/res/fonts/NotoSansCJK-Subset.ttf b/res/fonts/NotoSansCJK-Subset.ttf index 309a1eff1fa3cc3a83b3743568aa3f70a1d0c2a0..5fc12b63906c942fb148d660cd1c7467e470e252 100644 GIT binary patch delta 27789 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

46@%9=>5wQ2H8IY`hal4$;J;6^?^;vdgy~> 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 delta 26703 zcmbTe1y~i^`}TiN&+HkyySoDm6HqV^QBg$fZp8ou+%_t9fPsM`28!5m?Cv~vx98X% zyLj(S==pws@B6=g*PppQd(U38*0Y}He%6}U%${}E%ilX&er9%i<)Q%YxVP|X)uHa* zo-nJ(K;fD0t$bWY&dz)Yrq5iUz!R@l6)JbV+1&>aId52+JII(w+F5OF4Zn=wfzmsacSzu+#9?kYu`MGHC0mFj)22?2kJB0l} zrM>+Jb?efo>5uF{S6>?KKcGv{VCzN;))n{}>cB1odK4&9s|d`B%~-Z=@Svf?k|v@u z%*u2a1xGkK*jS_}%;BN@Tyz9Gs1ntsDnBoC*oVMUQBZx$JZ{n{L+uX`q-QLFbt`eY zlVjz{V|(13f6D(npxf4 zu2vIe^U8W$+u3lxoaM&d`*+XX3A*0zeERe0&YS1en~`&-HW_Z0HzsX-w(;@C(;H81 z+`ln)?HU@3%y|EJ)-;GT+Hr`ljW8TEiT$UzABu?QnIdKw~fW#q*gA)5E_6HJs zCU#8pO>CZ6EqSSsSSGP3m+Xm|63s-$w&Bf&mm6Mi`Fq1(8=h=zU9cp%ve~6B;MfOvsy%6b_R z>*LmUTkp0$)0SE5D#Ra%-xqJ+2gI+5kBeU#KPo;jeo*{?`2O*|;=9EA#aD_iz4q$b zJ!>beow(L}ZHcwT*A`iGZOxT62iEN4vS-bXHQU#0S+gEk6TfEdn$>G!*GyUy$ff6+ z?rYrE6k7di)pB6f>{Wq$9lokxN&u@mtZKi?ca`_50;}?K$!lMgo13$(%Cai`Dl6`5 z-0QekaWCVZ#666=8+R3m%ewNPm7Q01T-h2}S#M==z7}4Ye`V&CQtY$Xr?KZ9Mq{I5 zN5l?~9UMC-wtH;n*haApxwyrai!B>lFgAB=*4Xs1>0)iMIu|uoSn+ekM_|R%757%$ z<-7gjio+}Rtk}F_^@@cn=B}8tV)TmkE4)|aUY@l4((;|lc%+7 z)QG7VQ!b`VOsSZhF*#zg#AJ=J#R$tDExT)9c7e;uWyhE8S+;dq^s@QDGR|DS4qDb{ zSgl0i%QENQ=l6Lv}dCFbJSixU?!b&KsQ7q3_x zwK$Ti5sSwx9?AC(#AC7h;);vQMgNTc5&bgydi2@oW6|4z=;hH%q8CL+Mh}d3iY^gd zY|*(z_C*606h9|9t+#`A6p`%%3v9-~7Jw z+b_91ziHH$sL%GOPf;JE-bTHO+7{Jf@!qHgTxvyCj4B&dI4XZs?#T0zMq=^3fcTRHdp+{C$S=FXgJpX)id>D)SVGt9XT%*j8;n0ZNN%{(>3R1=7J8F44#Zp8kG-4RUyHgHN z*)wIwl*lRbrr4(hO&K(0;FJzi{H7@O$$wAYICtfl9P*0F3k7L zT&&5qN#7>Dbc~5f3(34mlP5Kr=J3Su zgz)v@apAGy%fq9?XNTLv!@@(u`-gW3Zya7eyli;piK`|qpBOW7(Zu-^?XxF#o#;2Q z?ZnJnY!kjtcr)S9guPt0jlTnoj~(BAe7Etf$CnuQaome>GspECS8nX;u|>zG8?$|4 zyDp>d%LLg$A@gpLdO67n+SZpikK ztsxsj)`!G}tPEKm5)-mCWJ$=PkOd);A#*~ehD;6#4;d3OIwUk?WJqAh;E_Kip^@8dKRSBvbR4%AsP=O#T@CTP~fnT|N00KV;ehT~;_#yCa;B9`o6?iT1O5mS? z7XvTw)2_g6j`Rd_LIuVI4hyUuSTnHnh?^t!j_5I>+la0sx{T;DTpV^_=!T&ShRz*2 zb?B6#b%)j&T6}2cfXDWL(*Z{Ub_e_suq9ws!2E#j0o?++1au7O5a1b5HK0g9!GOF0 zSp(7qq#N>W$fqGsfgxAO`5~K!u(Kf(hKwCDdPs{Qm4}oYQhG?q!3ze@7(8Wg_raXy z0a1gC4K6Y`&)^J$ZG*Kz83xW7SZ!e5fy#hOeg5n-qfb}=&Hfwx&vZA zw2o-qy0v%f=B*pGc5Pj#b%xgITkEY}wu)>ux>ebho-G@BAM!rnz0G@*_d4%2-b=g} zd(ZW@kMZv0?eFdF?e5*syS#Tqts(c)8!*Dcn!nB5|+z1J$Qm0q!4E4(7TW_i{1a`vj>RmrQkR}L@B%V_?k`RC@>nqO&t zym^b}p3R#yckw*#Im>gpXN0HSbCl;u&tT6W&k>&eJbTzZvv_9ols% zX7`%iZg#oZ#b$}k5}L&~E7`1Av%<|XH(l0rLDRlXdo}Ie)URpFrcImHZ~VBiXJfOm z(OC8P>G93ugU3^khaM+A;yhwKVmualM0(8h80#_Aqq|234;PR69(6n_x&Pt5(|w!! z2KV*uPVSZ6E4Y_%7aG}<8hvl{rqPQ==iT1By>)x#_S9{^+g`U-Zn17F+?Km7a+~iq z$8EOTIJaQ8o^Eb#E^hVRYPeN$EAN)WEt^|rH=CR0Cb&Lvedv16^{(r6*K@9?UH7l6GTFYu28u>Riq(e)SBkE%bj{=|B#>iX8LTeo&y=em{amaki? z&eb}9*11sUWS!%6j@3C(XJDO9b=ud-SNlnA`=i?TYhSK?uJ-QQ3u$dHVzu(u{9N-x&385buKBd) z{hAkRo~?Pj=B}DSHT%@;ShGdVbTxj|_*!FpjcnDwR{vc6L-nK8_f_9seM|L(>T{~s zuU@RWt-4lSuJ*awyN=baR=ZH`WVL?PJgU`pdf;@-X}{AfrzuW>PQ#r7occNScIxWn zL1RTox`tU9ym^r{h6?NvKeZCcf}YRRg(s;X7~sIsie z;wpWuS5^U@Ko^*E)~A?IYmRrD!c|S4Xz@Hbr{neapJ_SPO&dvG`@Myy(?93T@@*s9 z*0Ftl(KeHBxkXzL-*UFFb^Uiu)@@_+wfX(K%;va2`1NONl(uTCpR#7Fn^wZs)f`4e zTS30n6^%!Zo{AehJqC=E$*;$alPRBnH%czw?Pyrsi2Ge^EJ@yw{Q9rbNMj+ZR<;>^ zQwoiqj*p^IW6ptg{&{sC?DRYOz26Pe*7WnN=T=moo>st$6Vul9(J5>CD3*?9#q6Tq zpKpb;>dje_tbpEm*eN*$s%hx%WZ?f1-u!cS2U^N9JyYGO^%Rct7_i;cymqNnI5`is5A zzG8qlOdKJGh@-?w;uLY2xLmvmwdFc;J-MyyCoh(l%B$pf zd7Hdl-YM^u_sIw3!}2ltx_ncS?W-Rzs_$)z*$`C$!tzJ?)|PSu6Klmvvn? z_4ImXJ(r$W@22lwgNIw-q zhT{-26@ZXAJxPL)g=AA9WM`WkMIhvC0KuLs9zq_jQRyU2O+qWhu|7UzCvioC>zn)Mt32&S10Vu{UHR8br2c{Luk?%Lep{(n#trl z1W&5dd@>Dr)rQcb5Cre~5L#A)(8>csYew$V8$z4H5ZX%Q5x-nWgwSp_1iwxY+PgvU z&rd!==62NEZkpArL~@X&CE_%0_lDcXVwZAw<#ns5cPi)1d`S(}HIZ z7REqWv>ZY-)m&T^!V;>zvc0eK4HO(cZ3-2RT+-y0A7GN(&=6wA%@8w{Cd(jZb|M!bW{HHDwH?H4~kRIs6oy^%sB*NuA<~6 z#N3A<<{1VtZ&ea)hnO!jp~3u}AQqSovETuSg}y^9d<9~W2@s32!=hIq7CQp5_-TkG z*hz^`5KFR6DH24Wf3Da+2vwS-tc1Y(6&zfc8jDhIFXkDp@>nVtCGa)uCLw-VR zbRMF63`7q)-gq9wCUmN4G{j~s^NfS&RTyH6M2IbEvsHPBtt&(Hp<-?5K--ZJ?Y@6P zY)84>dcQ2OaO( z9AdA`Zez}XN7wP5}SSAsai6=HxV#Gy4I4&&$H zxgn0o2r-b2f+&0NHi#p)LJTPj)5=y*`#$!%ETz(1Sin9=7>F`Rv$Gw8Mn!&7@1##^y zi19ZeuA}qoIfgd0hPaXHZL(9Q%_|^op=VngK-`vxe1o`y8+Sa1xQp+*HbVTP9!Y|@ zoAvk5@ZP-;_ff+AjQF4q@sJC|!$Tn+=?(EH9Y4nW9v=wt#8ikUsm!Sg5KlLQc!p(X zS$1v=#PegR-o-2sFRh1oxfsMN%-2;J;x%@5oyKlZ)?0My_GO57yFt9)0pdd%csv8* z)8P=G^?>*n)9`m!h}>U@FXlshc@W~O`w-vI&YO1--_fyu7DD_G0`U`_;66e8k^u2* zJ~EN{|9TJNw|Nl1dz1GNe{kbZdY0525(<(;NJ4$G1CrPgl2n+yfh0eJq}+g{_J*Vl zgru`v-vEi{<&y0oB=Z6!>nfylCn2SO0x83FNEt6f%9H>p^HfM#dO*tB+zu(*bV%9H zK*})9>i zco|3~%8{>-N{Nt4vwi6wkji|7RF;&x2B|z9sgMMz66;nT0jY|e9y_r^r+bj9(c|iy zA=QY2RC5iaTB{&AkAqZu0Hit#An{-&)msdyejua<#UZ({0~adcRvJ=6M$>3GB=_}@ zJZP(l6QrhdAvKGHxGkqOs1KAaywbiDx%bH_G3`2B~KsNWIQL>iq&z-&~OTFcSo7^H+wkTx*q8>mp?R7e{e5$1jq)3>=C*$-(89oS0Qx1}Su zAZ=%=ci5vK?PQL2QRY9gL)zUP(w_3<4y3(PAnoJ!{mUR7SP$voY)FU3LpnT=yoYpT z5u~Gx@YrNX$D<*gV7-&iA)T%c=?on>L&wf~kRy=J@$)%Ge*QS53-cjeq>W256~8nI z(w~(6@@hy|dO*6$bX@BO={g6~jX{uZQlVQ5Al;6EbmtnC{AU$J_|Dx@`>C|(o`C%NeUK*+Wj$mV6p>ApbD*bZ{$1jt!4LC!W8a`t-U5#$`F?2vPAg`6uCa_-TP^PGX4 zFB|0iwF!;q-wwGzd-4Wy!6lFj6^C579ONR^AQvqPxtL1WaS1>!nGSNP0LZ0}LN1#b za=BWN%R57^;19VX9jY_}a^IU*8+k)^=ekED@)L67bC8=n zhukb5WY5Wvy)r;<(HF8eJ8$_Oa;qfBK6xP9+c1i@T_O8MLTgNs2P(jRib zAjm_h?y#Ydhtts!3m^v-h8#?lLdL@`hu(!es-D9W$fJWHkKyNW^&yXc26-YQ4zETS z&7_`?Co?ru211VL1$pWz$kV96bapm_kWLLXKVm zc`?(pxGm%*?vR(V&t+xokYmaa4vyu_`3g!KOKDdce4R@0 zB0|2w2yVtfzQvAiaj@K`(K|mN-(}f7Msa^F+cc*w8W;Tzg{R{-)qevsdXGXEdw`A5p}DJ$g96(N6N3cgN*{EZ!d zXMTS&r%4TVH zP>KmqinEgvU7(cQ0HxG>C}o_Xlx+{C+-NA}S3;?<2TH}OP%3?eQiXP^4u;}13re+k zDAj4JMk17&o1xU&38i)|D0S>HQ0f(jQhz3t2D_oS&^tFe((n@$_mfZ>v!kZn%!SA31L_-}+IhC?R8@gr$cvDhSHx!cfN0`LU;=j4uFXLLDd*>F}g1P$u7pGKE1+WgpY1#0)As zvn-TZ3}p6a*p<24phPkS^J_v`XhGrWwX&E7mh6YJjLyV7fU;r~l-LhY;uyv1c~I7# zhqA5*l!P)+HcW)Fkz-*~Jd`a%plp2wW&0{9JGp%q72Mqw%3i9o{~?q^v~&0ll%oTo z95C-y5p( z*1izRJ4*WQI+TCd;QbURAKF3rSOLnXA5gxWgYxwRly8wxzPk{r@`Eb;WKNSlLB%bo z!hNXX9jMYNsPaCjYDuVCG*m-?%5TzD{!du7azjn0kmpd-e}tN04AhLRpxQG{ftq<3 z)GSk>W*rBW(?iWM0%|TB)ZG1`@-kV?Um0q_EKm!lhgzf%VZEaKTyz`MVt+y{Aww{+PgyODQLE3AfEaVXSE^~eFJl_Q{583?s%O{h-kVOO1YLao*xYW33O z3)C9Vpw_$$wbps4&hw$x?g6z?R5@npAJxY8;ROK9O{6IPzSR8AVxo! z?T5658bI4aw?Z9W6zYh1Py^XvPzk8Pd7zHW1vR7~)KGf?s9`#J&0K^+9g~#=k-wmh z?Ms-ear>Z-r!y1UK%Gcq;e4Mo1L|ZtJDKgKY=9cUh^A8hY3yivDRKhpjJZ%}_J%r( zj?U)$oGj!x)Vb54&SP05gS1D*L!BQ8bpfMX_!esPWT;E>LtV-UmTiK%JTtiqbp<1d z-4Au;O{j6Fpsu2!)kmPNISqB~HK_4aYTX5>>#0-%>m;)M#=oI%9u9S@4eGYVPZxqyhouKZgmj{YLJ?IDZkUwF553|D~Goc<`3iTLO zIo=)WiOx_@mVtU|EY#C<`pizKXD2~D$ANdgA=C@)pk8bW_0klme?~yPd>iT&+PPK* z>UEB%n}x{-JJj15px&tq^=@sb_cD@iP#y->Q~nP#&PhC zPJFjJLH%Kn7f^pbhsv{B4X>ezg`i0-pvgULJQ_o5yb4;Acxe1qOKWxrn&&rYUUq2S8nl*2pta5q z&4)p>p+mltp|xX&eqW&Z(~%Ctp>-S$trP2Y-UY48ZfITKL+hRmS`Tk%J%eee*G*`B zYD4Sm4y|8%X#HcL4LA*LU=p;!>|{t@XaP*a(8bV(J%u)60JOm8(1J)XI}ND|EtGA; zIzbz?mXaQWHu^2Jv7XSzF-7BtL7OlI+Qh5SCS`{w8){*<}-&2=0jWf0a`R8SnLID2^%b>!DW4*#W2$4RBOdTXtArHt)v~^yQZyH zpsit@HH>&|Ftm6&AO9D$bz7k&l!LZmJ+zHXB`->~&2-4Vg;8zgVA)1v+wVf#$&I_l zLHlD9wB2-OF9*-Qcxe0izMqB;jD>cvFSJAaeCQu&hw0!ErsP;r!gj|#Lp#p;Cq_Zz zNvd}8B(zf~qOI6PGfOek!T*%J+U*t%?#1DT)L%aM8+7%9vt1qBkcZPO@ zPTf2Q?RE}mcl@E<-2m+#JAFW7k3?vXDdW>d(4Iv=`-_9}IRkmgf%Tfvy{QT9tuM5H zRA}!_!c=|W%=*YaKC}JT;?TYwwnO`o4%$!VJ*hi%gg_Vmgf1R}E`5fsRD-S>(6z$Q z^~um}PUIGJb0Ku=9`tmAoNP5pjTo2D(s}{0O(Hlp;z~YUW4^(9*17*9CT+oU%MHZOI|>)!~W{5 zfo`vx5qjMO==Ge*azfAR*CUIdHxLL_Y48xb3%z!E4BfQ~nM2+{ck2qhVLHM98YV$+ zkg(WgQ=u_2y->$D)a#6C}1!2p>+u58rGRG-@_Tj@Vn4QaQldj&;yH*9ngca z6Ar3ikubWE1<5SvA>|3nL#Rqei=t*M9KfLq7hcNo^Or!(Z2YnKwobITf_(GQ<<)*yX<_S(P@ls+DgL6r#B?*c={XYGgv<3B=nig)yzeN z18Wu)nzfyLg+99}Sr2^<9hlRYj3yidb4wDYZ(cFdk6eNt$+F0Cgkvd+<0k4g^!av1 zHb0tB;sqQi3uZ!Jn4U12g}b3IDocXMW$4kB2#qc_$s9uEmXsso2_0KnjZ7z0Y?(h{ z?w2w5F*Qgy`3w4TrgiyY=qucz$7)PNY#3J<^-4c-2znfyh~o%dRf2Fltmf2OP07|U z!ZjPAuk|ErpvPw;V@MM8b;F_aU#|Lk$2(Qyzg_i&r_eW0#l&1Bl)Qz$u?L}}n`V#? z&^PyC{x>u4Te=bEW~-fCgTBp`9E84|dD|XIDD@61vV$`2WZj)qYZsmSqc%AUeK&Kt zM<;R6_cGeO$D!}5N0^HJyPzNNCikHqOoV=jkso5)!+bw{mmMCV;Uf>BAB~27jHC5f z6!hcy3B5m2lTfac6QG}>yr z!p{GsI+v-&6_qT5ezh{OpM-vml3o|dFhW^wjD&s@WGVDpjPMroc6%{z2nvUOw+eX= z{oW+#_v?}!&>v8x2WOx^vBOM;xG!IcOhKsV9v7$qDFB+0RpsnP&|8ul|Io zvi}_n{W%*xe+>NvE4+uL|3gRq z;rsip_;#10{YLs z(33dQljv#Ebr@(wj=&J=kUwCEzT_tiX*CSF3E2WeDM!}8P{UzpCfNi-Z%59+Fucev z7`Ez!c1*T0dHrWt3t*(nM7W;bA~c@CjqHSxk(D!Uhmnb$XL<`G^JExV0%2s;2qOS4iLdR%5BjIsp?jh1}{qg-op0Y-U$ z7`(T~s1QO1nRAT!|`(RY21CFltivT0t}qxqjOypF(V@e)SMOfXt0 zFnDoc_#A-I_A3nE=P=q)Za>P}{tJu_B}sQOojifjkcY=m-ofZ<&&ij1WC)=&U73Pzc?qNH)|X5oapWqD?u@K^DMC5BPbHMO z2OaFO3Pw*3*j^f;Q@uJ7s?m#1@%+K)?M?a-mi68OqYumauzsIt=D%+)7=1a|`ksQ( zuO$hG(VzM0zXQeqD!~8c83P#AfUV>{jDf7flL=!`0O3FzT$KzYG&Y#(4Jk|f$T+f_ z`~xF^Y6c7?Oy^JrH{$t<5z4n{;* z7*q4Wm}U~%oK7XCe}OUMG>n<&V9dG$V|EOTIm2Mg%?)FoUF6GI7?B|`qO!r5&nOmr zg|RRR#v-O7x;D8CV=?7gvI)l0g)o*)ff3V$aG)(;1S6J)Ru+U2$MscA$?CN*)^HrG zb%7Djj@PGyk-(I0$O%g}dl-N8g|VAC z+p`MBJ{iV-c6=}oj6>^T9AVip=KchuKiLPyDGwN@H^MkG2FAI}FwPHwals$P#kMdm zQOQ5q=5id2E0tkfrJ~mw!?@mo`M==<WriGgo&`!nnr)bAL08hm7J;AdJTg zVLai~dHNH^U+nPjX)vCzgYklrzM2Q)O;Z?e+4kLB82_;S2iE<-F~hH3jE@}%Q~Ht8 zfBX#N6UW7;V8XyYy=VSEv*7apava8&YGf&luXNxmo%%|Nc!PrR^(%~TSqZ1mw`(xI zQ-$x%NEo?9n64j9VDLK9;BO6WNJnPCCS)S>U=yQYlNQ1z$HAs-f=yijo3;}+-M$_+ z;}UGVJ=tbzIz%##$*j_c`}d$*z#5&k73K#AGZ7@VJncAJcq4Nec0@Ud&5@vCu~KF!B%WM zY{g%~R)WS$vT`Xe*h&|LtxQGO$~Gg%U@I2}Tlt2tRS1QR_jKASw}P!o9oVWig3XDY zSL*~@^%Ahv0HMP*FThsoDs0XXu+?U}+P7h=(-*e7?P06e8g^T~B-rYofvrJ2Y%Ygj zbF*M;XplXyH41^volbbrYmXshA8d_HLP?wW5N>apg{&gqU~9(6oBaiw=WN2y&3llK zuzAgbtpyeK_JFNrX4qO~CA87Hg`F>#Ve_GkK3{m-IN#gWg3Xr|eCNW}&Xe4Qjr)9C zdw1CU^N>lfbtq5RuHzQiIx(uwbhQCNd3sX?df@UGJxLMPzWrmn9%~$3d^KF!GO|wLnl4cpRoat|dny-`Z z+J0|-+CICcSwU3FBt@I$qK-P7o${1PI&79pItv9El3pMqnU{3dOfHS8U)wCjx(`@) zU~SWBKuTSHRgPAyH#F%1hLNc#iTOz{*oN0XwDKTjE4>^>rXqjp*0b#A0c6(L#eN)p z&zX-oq%`5bkkcx$iNmyiUDLZj8TOs#(KTAQ2Ct-# z=zy%Ll}^_+8>YIFy`I@F)s!w9f zkSnbxM<0xi8y#y75#s8bLxOIh$PioPNLJ7)lG@F`iS}ZmP&l zzdLjc{0tnR8IvogOyR`jPH2M79jThx(9FiL97B9NU-g*+ht1?2 zfy061fsvA7%E^+HmJW9u&Yn$8ULwsGY-Dy&%5WHziyGU=ti+wg3ySh0d5olplJHBA z|Lp$(-lX}<`XUZfo+HE|a!TMSF*BZIkM2?W`{V(6&l&;;OhNbLU6mt~&D~A!)Oqfh zO(}^=o-o|F&E0I^m>%4BI^1_`c1Y&fb2#M6=wVi(TwLAW$itKb;X_oD#-_9VgZY7V z1%UEcsD(CM=eIS<``}EbXiBDR+RO}QCNqnf&CFruGV_@E%mU^YlU1y}tZn1+HMzdV zeRk@8+S+IF4tB>j;eGP9bf#gZH#3@<&8%j2GpCu`%xmU1Kg;G1Gikft#LOYsRZ9ab z!{VK;mTB=`HY>fwJC&>wR$1h=%3IDTY&Ec4P|kX)!1qbC##v|g=&_! z)dsb!&Q=%Hx4KzF;9?E4ror2qWz9lAYpxZE{?;-p27{~>)=CVqR$1{FX05jp5Nsvd zt<4Crc3Hc?+ht6ViIXUooV3f@>(G-WXIXNXC5gXEuCZhnOX66P$nPvflw`>Rmb|b^ z(8ZF-YLz0Ti96ZL4MGS!mm%s4kdTHi;g6+4+d%HbWvzDEv8*;>gXz^)S*U7?9PnM zQ7W^<(fL_xH0zCV4C~}L(!!XQT#vUU{YUBEq?8heJ%>(blY?>8v43RI3l?2t5pOPH zQCi6ZmT<?j*@+;PNk&DkrYRo9B!t_otCEmEO8{4_mVn#wzG+&BTj5K zd5~(>p+bI^ri=hbsl!l8Glyx1fN?CD%{sG_J9FsgP|7hT4kwo+vcw^BG)oebOB_!B zXUQ%{{?i6mN;8M)w34%&6Pc+@7AoU#&tbqJexj8-+3DZzIkfoC0h%&G915yznKrBw zE$#)avPmE5RI=L4KaDzKarl`sDx+EA7^lBIcPQX+%Avq-HyyD!6rh`_j-5>w)sbO` zrYWBs$#smK-wHciyJmSND{SW;GSzrWG>+^$x;mWPl_N)v>M7^KBX$JzyI!ZOeR-=733z{7W{VktAgp|f4!;e)r1rfx{vU;W-; zIJ!wW(EN9uxa0)<-dk=;j`l&yevPeu?>~PJ-L%v?W<~NIm;ZTS*J=BJ+04~Pho@F3 z6$wk8? zlPhT^9Fx$o!${dB|98YG2c&V}IJ?=ts}*<4cEdC%WqPw9lT+9%j2vcBvlw!krOZ;uZB{UAAdgws ztczl1ebWoYO>eUus+pb5?x<(>GJC_#>}&Q#BeTCb5bov>GZ0P8U^5urj zwfWinj5dzbA+)t*D?R+I%vM(PuyWe1oak-kwThyTRop6r0GT79wD z>TmVO5^JzE7)yD+Gz`nE5mpdltdZ78#9E;i?|oZojkYEr&I-38u+Eys)2WR-otlen zRwVyLv)x*3Ex{i=wOWQf)^aNrd#yMt4hO8&Ji$816Rb@*YHhK$;8v&kP$|Ei50ajn%{IV-2(dtl`!uYpONJnrAJwVyu-s z=i6*;vkqEEtW(yx)UNo;Qg$^l>U=x1L5ZGbKP!Wk&C0=(&DPcsE6kd0t+RGm{B@?| z%sA z%f5Y!pDBrk;{u0^`8;aBznRZIiq{6QY$x+O@3ghizt;Hct<@~<`icF<8)iycS&D&#NFQahRUYi;_kHU7LTb?Z#WT2%KA zW{GUETvd_YWLV}iF8pzv`7G*U2h&-27L~rES-_JweDM;)At03ovIPC-=bZdC>aXo8 zCxxRHe^{Ja#>;tLGfC!O=HKRX^F`Fijuh=FJ4!8JMgHiQPROig@eAHx4Mh<@c`ack z&+6~I?#RWfj~u-E$iwT8e7qLP#w(I6yf(3M=KVC2IO_$@#4qL-OSB};L&f4{iKX+h z#Kwyf%Sy+Kk_;SznYLS<%r-(n?iMnbqP5rB&&!ztW;!#Yb->KT@x@`yF?KX+Y-h8m zWqviknVPAXs;Niq?rb(_U&1VjEBqR(40r|0Z&j}I!2`8%gWrVt;U>S@^2aT+quCL+ z`OR1;?wF&@xw!8L9-sN8*K2&`7hmteUmyRLP2i81dC6Ea%D0P|uR>~XERy*}n&V5f z|InCXQ84qP$)9LS--T~cv0coX_IP2vkSJ^ub_u(M1Hw_^lyFw~Q@A2r6K)81geSra z;f?T4crSbveu!)*>Y^oP60?c<#6n^jv7%U6bP{WbwL~|uk=R6RCbke;imk;qVmq;*ZWecle~A0VW8w+% zjCfwWC|(w?iuc3^;$!id_*{G?z7_uwKZu{iFXA`x2WOHf$&xDBq;ygSDT|a{$|Dt! z3Q5JJ(o!XyE7g}gq~=m<$zSRyb(MNZy`(-;KWU&eL>eZIkbmP*T|mC`C{t+Za+C~cK?NV}zd(gEq1bV52UotG|2*QJ}%9qGRGKzbxS zk^YumN*|<8(swCI7Gz1bwmE-IIh%gGhw%CeJOLw1(y%dT=Gxv}giw~$-P zt>t!dN4bmK%`W$ld&zy}{_-Gsm^?xbl0)TD@@RRyJW-w`Pm!bLC31|sR^BM@kax@b zrQ}nJDy5Zj zN(H5|;-pkpYAN-VhKh&MOz~2@mDY;AjpD1cS2`=*m7dA~Wv~*U1S%nlT^XZHRHiGl zl=(`uvRsK()+&k0W@WpwOWC9BQw}IcmD9?3<)U&!xvkt&9w?8Mr^<8Xjq;E3QTd|$ z;Fr3hDyud%qncCAqn1?5s1?=PYCW}q>Z&$U8>`J!FV$OZ)lv0P+p6u<_G$;Uv)Wbd zuJ%-Wt9{k}>Ogg{I#eC52C0$i0(FtPRE<^R)kJl(x=%f!o>I@L7u7%2tLk0#srp=f zuYOX$s^8V08t>NCR4u)hNz0<;iQ3lPEMl*(xoQnHcdfDJskP8rYChTsZKM{a*|qUn zxHdHd00y{q0s@1ytA z2kHU(a6L#LsfX(k`ZRsE9;vU@6ZDPxd@)LWDcl#kO0ASiitDdA?AXN#oUhA!aK5e+ z5`>MycHs|Uk8n^pCY%<|373Vd!gb-Ma94OLycFIF{|Fz1Z^@5-kwrsHCuSD2^ARwG z#j;{0u}bozV4TH7G|0_Q=Bc% z6QjkYc0M5{UQ7_Th&#pI;sNovcv3toUJx%OKR4#S_)vTz{w2N;UyJXOpCa>F{F?kE z89|bgpC)7SNirFwtWpjsuT+rFlqoKikt$17`DB@TQUg9&#!K>%I!K+QZcl51mPnHc8v0ozfm@zjRPKE}fLl zNEf6(r5n;M>8^B7dgyp8jr3f4C4H1WOFv}DqAbhlh}DsgJlhA)k`3B|qlozWhY~OMWeXlt0Vgk{@~_@o_illOK4KjSsxZ z!$;l}Q_3jim5NFgrJ7PhaaI~Ajg-cUr_w@csrV@Nwn{t2U+JRsPW_jwxr93(6(srgBHQuRK(qD9@A^ z%3I~V@=5us{8XVzs-l`|CN-CuS1qNMRV%4=)cUE<+-ahECO>zlbw{<0>Z|&x{%Xfx z58>&P{1~1=>JW99IzkOrqtu0Jw7N`PsjgEus$10kDj(6Ko>woam(^?PJ@uLTLj9nA zR==q~)Fe&NBu&#YXqmOFTHdG|gE?OtXl_~~%|mOVHRp}xt+X~;pcbNy(nf0&v`N}r zZGpB(TdXb9VzoGJjkZPGsqNPGX@`=Z{&QNpqTNV+2GCROZ|#-#R(sE<0e#n!bm3nQ z1j?TLNT7mxQN6fcS+A;B(_Qt(dNbWe_w&#@=$(?E7SuQSX+cAipBEIOPtvFA)Ac!e zlpe2d&^OsW*uI#N=0bD18E0-YcmDd%RPqs4PA|&;I>MS!|8a!9V$L@gn2XG?e;;AZ z=#(R@x!7@pHJ3P!u;$W~Vx*?0+3!%@zOKejJK&mo|L5`6+?R5^HTSDSZQs+5 zx3(YZQuBZsYx`*){GZ2N^H9oh*F5~6$6Z@e%5hiArxnl&X+^YRn!SWpN-Lw4(<+!p zwEt7fz4&BZ#c>?>{LVSwbL3DcRv;>}@ujjbiVz_t-=>nN4T$>5?{3I{trTmiG&MWv$evAJD0-Az1JPE$w2LaFq+CqEi z0G*&KJO|Iii_iml!AsB^B4Gdwgx4V&CP56u!Xj7!-@`iC0I84$>97s9!%q0whHTgi zhoJz9p%l)*IXDj&;R;m2pMnV~yhJOUq<$hw3=%`cP%%tQ6>%a#%vFbQWmbuFks-E= zonnv37W+i5I4n+z5^+YH6Boo~@vEp5zl)oqTHKMAHdh#Cl57Pj=dvQ2NczRLmzGPnk5^q|-6Xrn4AKl{%L&lb&S$EWm_P zcPGVtnNB1fNN<@3KHouyC$LE@7HeoeTgZ~lbDtZrgd7ij9$)?tx>{A(ch$sD^%h!Q@+JWS&eD(!z1FvcGk%Q+oZGX zimK^nOUFqaA=Bjy`MHdjvoS^1%TyB}`m?x1S9&zDEN?=MV||TeZpR#oX~WXdu>D3a zw96*dD3?OFg7K8+P|G3KToh}q(Q2oaiDDfxVindA%NND!h-QV;J|1dKrHQE45>(66 ztb;V47CObMqSf>^a%KCl77z4lFnXo6n#dB2Qma`CThF$lOAe8|&6z6*&s*A}D7<1t za|c47@|hk0rQ^+N2VSfW@qBNM&{@NfM(DOi2tPpqAE!crMxl;Qg(A?N81!c8ed6qb zOvEM+u{m`gHXN~0_#4>8&0r@su?CuD_fhkHuE-Nb9@boQTJyKD25MOoXsmHj^Ra=( zHqaPmT*&a3J(!_M>!zw!wmuqdCA;xpqsxkrINa z=of+Ati;fT4pwTJf~OeU++s8-mFD`QLGgVkDEhtN2~I{<8Aj3&4nv013VkNgR`kbf zh+By`4 Node & Sicherheit.", "faq_d_mgmt_1_q": "Wie starte oder stoppe ich den Node?", @@ -1226,6 +1226,7 @@ "miner_fee": "Miner-Gebühr", "mining": "Mining", "mining_active": "Aktiv", + "mining_address": "Mining-Adresse", "mining_address_copied": "Mining-Adresse kopiert", "mining_all_time": "Gesamt", "mining_already_saved": "Pool-URL bereits gespeichert", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "Testen", "mining_benchmark_tooltip": "Optimale Thread-Anzahl für diese CPU finden", "mining_block_copied": "Block-Hash kopiert", + "mining_card_click_to_shield": "Klicken, um gereifte Belohnungen jetzt abzuschirmen.", + "mining_card_tooltip": "Solo-Mining-Belohnungen gehen an Ihre Mining-Adressen (transparent, R…). Diese Adressen können keine Zahlungen empfangen. Belohnungen werden automatisch abgeschirmt, sobald sie gereift sind.", "mining_chart_1m_ago": "vor 1m", "mining_chart_5m_ago": "vor 5m", "mining_chart_now": "Jetzt", @@ -1283,6 +1286,7 @@ "mining_payout_address": "Auszahlungsadresse", "mining_payout_foreign": "⚠ Diese Auszahlungsadresse befindet sich nicht in Ihrer aktuellen Wallet — geschürfte Belohnungen würden an eine andere Wallet gehen. Aktualisieren Sie sie, wenn Sie die Wallet gewechselt haben.", "mining_payout_invalid": "Keine gültige DragonX-Adresse — vor dem Start korrigieren, sonst gehen die Mining-Belohnungen verloren.", + "mining_payout_needs_shielded": "Pools zahlen mit gewöhnlichen Transaktionen aus, die bei DragonX keine Mining-Adresse (transparent, R…) erreichen können. Verwenden Sie eine abgeschirmte Adresse (sie beginnt mit zs) als Auszahlungsadresse.", "mining_payout_tooltip": "Adresse für Mining-Belohnungen", "mining_pool": "Pool", "mining_pool_fee": "Gebühr", @@ -1295,6 +1299,8 @@ "mining_refresh": "Aktualisieren", "mining_remove": "Entfernen", "mining_reset_defaults": "Standardwerte zurücksetzen", + "mining_rewards": "Mining-Belohnungen", + "mining_rewards_unshielded": "Noch nicht abgeschirmt", "mining_save_payout_address": "Auszahlungsadresse speichern", "mining_save_pool_url": "Pool-URL speichern", "mining_saved_addresses": "Gespeicherte Adressen:", @@ -1328,10 +1334,10 @@ "network_fee": "NETZWERKGEBÜHR", "network_hashrate": "Netzwerk-Hashrate", "new": "+ Neu", + "new_mining_address": "Neue Mining-Adresse", + "new_mining_address_created": "Neue Mining-Adresse erstellt", "new_shielded_created": "Neue abgeschirmte Adresse erstellt", - "new_t_address": "Neue T-Adresse", "new_t_transparent": "Neue t-Adresse (Transparent)", - "new_transparent_created": "Neue transparente Adresse erstellt", "new_z_address": "Neue Z-Adresse", "new_z_shielded": "Neue z-Adresse (Abgeschirmt)", "no_addresses": "Keine Adressen gefunden. Erstellen Sie eine mit den Schaltflächen oben.", @@ -1696,6 +1702,8 @@ "send_from_this_address": "Von dieser Adresse senden", "send_go_to_receive": "Zum Empfangen", "send_keep": "Behalten", + "send_mining_addr_blocked": "Dies ist eine Mining-Adresse (transparent). Bei DragonX können solche Adressen nur Mining-Belohnungen empfangen – das Netzwerk lehnt Zahlungen an sie ab. Bitten Sie den Empfänger um eine abgeschirmte Adresse (sie beginnt mit zs).", + "send_mining_addr_short": "Mining-Adresse – kann keine Zahlungen empfangen", "send_network_fee": "NETZWERKGEBÜHR", "send_no_balance": "Kein Guthaben", "send_no_recent": "Keine kürzlichen Sendungen", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxID in Zwischenablage kopiert", "send_txid_label": "TxID: %s", "send_valid_shielded": "Gültige abgeschirmte Adresse", - "send_valid_transparent": "Gültige transparente Adresse", "send_wallet_empty": "Ihre Wallet ist leer", "send_yes_clear": "Ja, leeren", "sender_balance": "Absender: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "Laufenden Knoten stoppen?", "switch_stopnode_warn": "Es läuft bereits ein Knoten, den diese Wallet nicht gestartet hat.", "syncing": "Synchronisiere...", - "t_address": "T-Adresse", "t_addresses": "T-Adressen", "test_connection": "Testen", "theme": "Design", @@ -1964,8 +1970,6 @@ "transfer_sent": "Überweisung gesendet", "transfer_sent_desc": "Ihre Überweisung wurde an das Netzwerk gesendet.", "transfer_to": "Überweisen an:", - "transparent": "Transparent", - "transparent_address": "Transparente Adresse", "try_again": "Erneut versuchen", "tt_addr_url": "Basis-URL zum Anzeigen von Adressen in einem Block-Explorer", "tt_address_book": "Gespeicherte Adressen für schnelles Senden verwalten", @@ -2037,6 +2041,7 @@ "tt_low_spec": "Alle aufwendigen visuellen Effekte deaktivieren\\nHotkey: Ctrl+Shift+Down", "tt_merge": "Mehrere UTXOs einer Adresse zusammenführen", "tt_mine_idle": "Mining automatisch starten, wenn das\\nSystem inaktiv ist (keine Tastatur-/Mauseingabe)", + "tt_new_mining_address": "Erstellt eine transparente Adresse (R…) für Solo-Mining-Belohnungen. Sie kann keine Zahlungen empfangen – teilen Sie dafür eine abgeschirmte Adresse.", "tt_noise": "Körnungstextur-Intensität (0% = aus, 100% = maximum)", "tt_open_app_dir": "Den ObsidianDragon-Ordner (Einstellungen, Themes, Logs) im Dateimanager öffnen", "tt_open_data_dir": "Den Ordner mit Ihren Wallet- und Blockchain-Daten im Dateimanager öffnen", diff --git a/res/lang/es.json b/res/lang/es.json index 6905756..ad3e61d 100644 --- a/res/lang/es.json +++ b/res/lang/es.json @@ -25,6 +25,7 @@ "about_website": "Sitio Web", "acrylic": "Acrílico", "add": "Agregar", + "addr_type_mining": "Minería", "address": "Dirección", "address_book_add": "Agregar Dirección", "address_book_add_new": "Agregar Nueva", @@ -172,21 +173,20 @@ "balance_history_collecting": "Historial de saldo — recopilando datos...", "balance_layout": "Diseño de Saldo", "balance_layout_switched": "Diseño: %s", + "balance_mining_fmt": "Recompensas de minería: %.8f", "balance_mining_rate": "Minando %s", "balance_shielded_fmt": "Protegido: %.8f", "balance_syncing_pct": "Sincronizando %.1f%%", - "balance_transparent_fmt": "Transparente: %.8f", "baltab_market": "Mercado", "baltab_market_price_4dp": "Mercado: $%.4f", "baltab_market_price_8dp": "Mercado: $%.8f", + "baltab_mining_addresses_count": "%d direcciones de minería", + "baltab_mining_amount": "Recompensas de minería %.8f", "baltab_pct_change_24h": "%s%.1f%% 24h", "baltab_pct_of_total_zaddr": "%.0f%% del total · %d Z-addr", "baltab_shielded": "Blindado", "baltab_shielded_amount": "Blindado %.8f", - "baltab_t_addresses_count": "%d T-addresses", "baltab_total_balance": "Saldo total", - "baltab_transparent": "Transparente", - "baltab_transparent_amount": "Transparente %.8f", "ban": "Bloquear", "banned_peers": "Nodos Bloqueados", "block": "Bloque", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "La imagen se copia en la app para que siga disponible si el original se mueve.", "contact_avatar_remove": "Quitar", "contact_avatar_shielded": "Blindada", - "contact_avatar_transparent": "Transparente", + "contact_chip_mining": "Solo minería", "contact_global": "Mostrar en todas las carteras (contacto global)", "contact_global_badge_tt": "Contacto global — visible en todas las carteras", "contact_global_tt": "Activado: este contacto permanece visible sin importar qué cartera cargues. Desactivado: pertenece solo a la cartera actual.", @@ -707,8 +707,8 @@ "export_tx_success": "Transacciones exportadas exitosamente", "export_tx_title": "Exportar Transacciones a CSV", "export_viewing_key": "Exportar Clave de Vista", + "failed_create_mining_address": "No se pudo crear la dirección de minería", "failed_create_shielded": "Error al crear dirección protegida", - "failed_create_transparent": "Error al crear dirección transparente", "faq": "Preguntas frecuentes", "faq_d_mgmt_1_a": "El nodo integrado se inicia automáticamente con la cartera y se detiene cuando corresponde, así que normalmente no necesitas administrarlo a mano. Los controles avanzados (incluido reiniciar el daemon) están en Ajustes > Nodo y seguridad.", "faq_d_mgmt_1_q": "¿Cómo inicio o detengo el nodo?", @@ -1226,6 +1226,7 @@ "miner_fee": "Tarifa de minero", "mining": "Minería", "mining_active": "Activo", + "mining_address": "Dirección de minería", "mining_address_copied": "Dirección de minería copiada", "mining_all_time": "Todo el Tiempo", "mining_already_saved": "URL del pool ya guardada", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "Probando", "mining_benchmark_tooltip": "Encontrar el número óptimo de hilos para esta CPU", "mining_block_copied": "Hash de bloque copiado", + "mining_card_click_to_shield": "Haz clic para blindar ahora las recompensas maduras.", + "mining_card_tooltip": "Las recompensas de minería en solitario llegan a tus direcciones de minería (transparentes, R…). Esas direcciones no pueden recibir pagos. Las recompensas se blindan automáticamente cuando maduran.", "mining_chart_1m_ago": "hace 1m", "mining_chart_5m_ago": "hace 5m", "mining_chart_now": "Ahora", @@ -1283,6 +1286,7 @@ "mining_payout_address": "Dirección de Pago", "mining_payout_foreign": "⚠ Esta dirección de pago no está en tu cartera actual — las recompensas minadas irían a otra cartera. Actualízala si cambiaste de cartera.", "mining_payout_invalid": "No es una dirección DragonX válida — corrígela antes de empezar, o se pierden las recompensas de minería.", + "mining_payout_needs_shielded": "Los pools pagan con transacciones normales, que en DragonX no pueden llegar a una dirección de minería (transparente, R…). Usa una dirección blindada (empieza por zs) como dirección de pago.", "mining_payout_tooltip": "Dirección para recibir recompensas de minería", "mining_pool": "Pool", "mining_pool_fee": "Comisión", @@ -1295,6 +1299,8 @@ "mining_refresh": "Actualizar", "mining_remove": "Eliminar", "mining_reset_defaults": "Restablecer Valores", + "mining_rewards": "Recompensas de minería", + "mining_rewards_unshielded": "Aún sin blindar", "mining_save_payout_address": "Guardar dirección de pago", "mining_save_pool_url": "Guardar URL del pool", "mining_saved_addresses": "Direcciones Guardadas:", @@ -1328,10 +1334,10 @@ "network_fee": "COMISIÓN DE RED", "network_hashrate": "Tasa de Hash de la Red", "new": "+ Nuevo", + "new_mining_address": "Nueva dirección de minería", + "new_mining_address_created": "Nueva dirección de minería creada", "new_shielded_created": "Nueva dirección protegida creada", - "new_t_address": "Nueva Dirección T", "new_t_transparent": "Nueva dirección t (Transparente)", - "new_transparent_created": "Nueva dirección transparente creada", "new_z_address": "Nueva Dirección Z", "new_z_shielded": "Nueva dirección z (Blindada)", "no_addresses": "No se encontraron direcciones. Cree una usando los botones de arriba.", @@ -1696,6 +1702,8 @@ "send_from_this_address": "Enviar desde esta dirección", "send_go_to_receive": "Ir a Recibir", "send_keep": "Mantener", + "send_mining_addr_blocked": "Esta es una dirección de minería (transparente). En DragonX solo pueden recibir recompensas de minería; la red rechaza los pagos a ellas. Pide al destinatario una dirección blindada (empieza por zs).", + "send_mining_addr_short": "Dirección de minería: no puede recibir pagos", "send_network_fee": "COMISIÓN DE RED", "send_no_balance": "Sin saldo", "send_no_recent": "No hay envíos recientes", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxID copiado al portapapeles", "send_txid_label": "TxID: %s", "send_valid_shielded": "Dirección protegida válida", - "send_valid_transparent": "Dirección transparente válida", "send_wallet_empty": "Tu cartera está vacía", "send_yes_clear": "Sí, Limpiar", "sender_balance": "Remitente: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "¿Detener el nodo en ejecución?", "switch_stopnode_warn": "Ya hay un nodo en ejecución que esta cartera no inició.", "syncing": "Sincronizando...", - "t_address": "Dirección T", "t_addresses": "Direcciones T", "test_connection": "Probar", "theme": "Tema", @@ -1964,8 +1970,6 @@ "transfer_sent": "Transferencia Enviada", "transfer_sent_desc": "Su transferencia ha sido enviada a la red.", "transfer_to": "Transferir a:", - "transparent": "Transparente", - "transparent_address": "Dirección Transparente", "try_again": "Reintentar", "tt_addr_url": "URL base para ver direcciones en un explorador de bloques", "tt_address_book": "Administrar direcciones guardadas para envío rápido", @@ -2037,6 +2041,7 @@ "tt_low_spec": "Desactivar todos los efectos visuales pesados\\nAtajo: Ctrl+Shift+Down", "tt_merge": "Consolidar múltiples UTXOs en una dirección", "tt_mine_idle": "Iniciar minería automáticamente cuando el\\nsistema esté inactivo (sin entrada de teclado/ratón)", + "tt_new_mining_address": "Crea una dirección transparente (R…) para recompensas de minería en solitario. No puede recibir pagos; para eso comparte una dirección blindada.", "tt_noise": "Intensidad de textura granulada (0% = apagado, 100% = máximo)", "tt_open_app_dir": "Abrir la carpeta de ObsidianDragon (configuración, temas, registros) en el explorador de archivos", "tt_open_data_dir": "Abre en el gestor de archivos la carpeta con los datos de tu cartera y de la blockchain", diff --git a/res/lang/fr.json b/res/lang/fr.json index 08a70dc..004850d 100644 --- a/res/lang/fr.json +++ b/res/lang/fr.json @@ -25,6 +25,7 @@ "about_website": "Site web", "acrylic": "Acrylique", "add": "Ajouter", + "addr_type_mining": "Minage", "address": "Adresse", "address_book_add": "Ajouter une adresse", "address_book_add_new": "Ajouter", @@ -172,21 +173,20 @@ "balance_history_collecting": "Historique du solde — collecte des données...", "balance_layout": "Disposition du solde", "balance_layout_switched": "Disposition : %s", + "balance_mining_fmt": "Récompenses de minage : %.8f", "balance_mining_rate": "Minage %s", "balance_shielded_fmt": "Blindé : %.8f", "balance_syncing_pct": "Synchronisation %.1f%%", - "balance_transparent_fmt": "Transparent : %.8f", "baltab_market": "Marché", "baltab_market_price_4dp": "Marché : %.4f $", "baltab_market_price_8dp": "Marché : %.8f $", + "baltab_mining_addresses_count": "%d adresses de minage", + "baltab_mining_amount": "Récompenses de minage %.8f", "baltab_pct_change_24h": "%s%.1f%% 24h", "baltab_pct_of_total_zaddr": "%.0f%% du total · %d Z-addr", "baltab_shielded": "Protégé", "baltab_shielded_amount": "Protégé %.8f", - "baltab_t_addresses_count": "%d T-addresses", "baltab_total_balance": "Solde total", - "baltab_transparent": "Transparent", - "baltab_transparent_amount": "Transparent %.8f", "ban": "Bannir", "banned_peers": "Pairs bannis", "block": "Bloc", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "L'image est copiée dans l'application pour rester disponible si l'original est déplacé.", "contact_avatar_remove": "Retirer", "contact_avatar_shielded": "Blindée", - "contact_avatar_transparent": "Transparente", + "contact_chip_mining": "Minage seul", "contact_global": "Afficher dans tous les portefeuilles (contact global)", "contact_global_badge_tt": "Contact global — visible dans tous les portefeuilles", "contact_global_tt": "Activé : ce contact reste visible quel que soit le portefeuille chargé. Désactivé : il appartient au portefeuille actuel uniquement.", @@ -707,8 +707,8 @@ "export_tx_success": "Transactions exportées avec succès", "export_tx_title": "Exporter les transactions en CSV", "export_viewing_key": "Exporter la clé de visualisation", + "failed_create_mining_address": "Impossible de créer l'adresse de minage", "failed_create_shielded": "Échec de la création de l'adresse blindée", - "failed_create_transparent": "Échec de la création de l'adresse transparente", "faq": "FAQ", "faq_d_mgmt_1_a": "Le nœud intégré démarre automatiquement avec le portefeuille et s'arrête quand il le faut, donc vous n'avez normalement pas besoin de le gérer manuellement. Les contrôles avancés (y compris le redémarrage du démon) se trouvent dans Paramètres > Nœud et sécurité.", "faq_d_mgmt_1_q": "Comment démarrer ou arrêter le nœud ?", @@ -1226,6 +1226,7 @@ "miner_fee": "Frais de mineur", "mining": "Minage", "mining_active": "Actif", + "mining_address": "Adresse de minage", "mining_address_copied": "Adresse de minage copiée", "mining_all_time": "Tout le temps", "mining_already_saved": "URL du pool déjà enregistrée", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "Test", "mining_benchmark_tooltip": "Trouver le nombre optimal de threads pour ce CPU", "mining_block_copied": "Hash du bloc copié", + "mining_card_click_to_shield": "Cliquez pour blinder dès maintenant les récompenses arrivées à maturité.", + "mining_card_tooltip": "Les récompenses de minage en solo arrivent sur vos adresses de minage (transparentes, R…). Ces adresses ne peuvent pas recevoir de paiements. Les récompenses sont blindées automatiquement une fois arrivées à maturité.", "mining_chart_1m_ago": "il y a 1m", "mining_chart_5m_ago": "il y a 5m", "mining_chart_now": "Maintenant", @@ -1283,6 +1286,7 @@ "mining_payout_address": "Adresse de paiement", "mining_payout_foreign": "⚠ Cette adresse de paiement ne fait pas partie de votre portefeuille actuel — les récompenses minées iraient vers un autre portefeuille. Mettez-la à jour si vous avez changé de portefeuille.", "mining_payout_invalid": "Adresse DragonX invalide — corrigez-la avant de démarrer, sinon les récompenses de minage sont perdues.", + "mining_payout_needs_shielded": "Les pools paient avec des transactions ordinaires, qui ne peuvent pas atteindre une adresse de minage (transparente, R…) sur DragonX. Utilisez une adresse blindée (elle commence par zs) comme adresse de paiement.", "mining_payout_tooltip": "Adresse pour recevoir les récompenses de minage", "mining_pool": "Pool", "mining_pool_fee": "Frais", @@ -1295,6 +1299,8 @@ "mining_refresh": "Actualiser", "mining_remove": "Supprimer", "mining_reset_defaults": "Réinitialiser les paramètres", + "mining_rewards": "Récompenses de minage", + "mining_rewards_unshielded": "Pas encore blindées", "mining_save_payout_address": "Enregistrer l'adresse de paiement", "mining_save_pool_url": "Enregistrer l'URL du pool", "mining_saved_addresses": "Adresses enregistrées :", @@ -1328,10 +1334,10 @@ "network_fee": "FRAIS RÉSEAU", "network_hashrate": "Hashrate du réseau", "new": "+ Nouveau", + "new_mining_address": "Nouvelle adresse de minage", + "new_mining_address_created": "Nouvelle adresse de minage créée", "new_shielded_created": "Nouvelle adresse blindée créée", - "new_t_address": "Nouvelle adresse T", "new_t_transparent": "Nouvelle adresse t (Transparente)", - "new_transparent_created": "Nouvelle adresse transparente créée", "new_z_address": "Nouvelle adresse Z", "new_z_shielded": "Nouvelle adresse z (Blindée)", "no_addresses": "Aucune adresse trouvée. Créez-en une avec les boutons ci-dessus.", @@ -1696,6 +1702,8 @@ "send_from_this_address": "Envoyer depuis cette adresse", "send_go_to_receive": "Aller à Recevoir", "send_keep": "Conserver", + "send_mining_addr_blocked": "Ceci est une adresse de minage (transparente). Sur DragonX, elles ne peuvent recevoir que des récompenses de minage — le réseau refuse les paiements vers elles. Demandez au destinataire une adresse blindée (elle commence par zs).", + "send_mining_addr_short": "Adresse de minage — ne peut pas recevoir de paiements", "send_network_fee": "FRAIS RÉSEAU", "send_no_balance": "Pas de solde", "send_no_recent": "Aucun envoi récent", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxID copié dans le presse-papiers", "send_txid_label": "TxID : %s", "send_valid_shielded": "Adresse blindée valide", - "send_valid_transparent": "Adresse transparente valide", "send_wallet_empty": "Votre portefeuille est vide", "send_yes_clear": "Oui, effacer", "sender_balance": "Expéditeur : %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "Arrêter le nœud en cours d'exécution ?", "switch_stopnode_warn": "Un nœud que ce portefeuille n'a pas démarré est déjà en cours d'exécution.", "syncing": "Synchronisation...", - "t_address": "Adresse T", "t_addresses": "Adresses T", "test_connection": "Tester", "theme": "Thème", @@ -1964,8 +1970,6 @@ "transfer_sent": "Transfert envoyé", "transfer_sent_desc": "Votre transfert a été soumis au réseau.", "transfer_to": "Transférer à :", - "transparent": "Transparent", - "transparent_address": "Adresse transparente", "try_again": "Réessayer", "tt_addr_url": "URL de base pour consulter les adresses dans un explorateur de blocs", "tt_address_book": "Gérer les adresses enregistrées pour un envoi rapide", @@ -2037,6 +2041,7 @@ "tt_low_spec": "Désactiver tous les effets visuels lourds\\nRaccourci : Ctrl+Shift+Down", "tt_merge": "Consolider plusieurs UTXOs vers une adresse", "tt_mine_idle": "Démarrer le minage automatiquement quand le\\nsystème est inactif (aucune entrée clavier/souris)", + "tt_new_mining_address": "Crée une adresse transparente (R…) pour les récompenses de minage en solo. Elle ne peut pas recevoir de paiements — partagez une adresse blindée pour cela.", "tt_noise": "Intensité de texture grainée (0% = désactivé, 100% = maximum)", "tt_open_app_dir": "Ouvrir le dossier ObsidianDragon (paramètres, thèmes, journaux) dans le gestionnaire de fichiers", "tt_open_data_dir": "Ouvrir le dossier contenant les données de votre portefeuille et de la blockchain dans le gestionnaire de fichiers", diff --git a/res/lang/ja.json b/res/lang/ja.json index e487fbc..7e106a8 100644 --- a/res/lang/ja.json +++ b/res/lang/ja.json @@ -25,6 +25,7 @@ "about_website": "ウェブサイト", "acrylic": "アクリル", "add": "追加", + "addr_type_mining": "マイニング", "address": "アドレス", "address_book_add": "アドレスを追加", "address_book_add_new": "新規追加", @@ -172,21 +173,20 @@ "balance_history_collecting": "残高履歴 — データを収集中...", "balance_layout": "残高レイアウト", "balance_layout_switched": "レイアウト: %s", + "balance_mining_fmt": "マイニング報酬:%.8f", "balance_mining_rate": "マイニング中 %s", "balance_shielded_fmt": "シールド: %.8f", "balance_syncing_pct": "同期中 %.1f%%", - "balance_transparent_fmt": "透明: %.8f", "baltab_market": "市場", "baltab_market_price_4dp": "市場価格: $%.4f", "baltab_market_price_8dp": "市場価格: $%.8f", + "baltab_mining_addresses_count": "マイニングアドレス %d 件", + "baltab_mining_amount": "マイニング報酬 %.8f", "baltab_pct_change_24h": "%s%.1f%% 24h", "baltab_pct_of_total_zaddr": "全体の%.0f%% · %d Z-addr", "baltab_shielded": "シールド", "baltab_shielded_amount": "シールド %.8f", - "baltab_t_addresses_count": "%d 個のT-address", "baltab_total_balance": "合計残高", - "baltab_transparent": "透明", - "baltab_transparent_amount": "透明 %.8f", "ban": "ブロック", "banned_peers": "ブロック済みピア", "block": "ブロック", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "画像はアプリ内にコピーされ、元のファイルが移動しても利用できます。", "contact_avatar_remove": "削除", "contact_avatar_shielded": "シールド", - "contact_avatar_transparent": "透明", + "contact_chip_mining": "マイニング専用", "contact_global": "すべてのウォレットで表示(グローバル連絡先)", "contact_global_badge_tt": "グローバル連絡先 — すべてのウォレットで表示", "contact_global_tt": "オン:この連絡先はどのウォレットを読み込んでも表示されます。オフ:現在のウォレットにのみ属します。", @@ -707,8 +707,8 @@ "export_tx_success": "取引のエクスポートに成功しました", "export_tx_title": "取引をCSVにエクスポート", "export_viewing_key": "閲覧鍵をエクスポート", + "failed_create_mining_address": "マイニングアドレスを作成できませんでした", "failed_create_shielded": "シールドアドレスの作成に失敗しました", - "failed_create_transparent": "透明アドレスの作成に失敗しました", "faq": "FAQ", "faq_d_mgmt_1_a": "組み込みノードはウォレットと同時に自動的に起動し、適切なタイミングで停止するため、通常は手動で管理する必要はありません。高度な操作(デーモンの再起動を含む)は設定 > ノードとセキュリティにあります。", "faq_d_mgmt_1_q": "ノードの起動・停止はどうすればいいですか?", @@ -1226,6 +1226,7 @@ "miner_fee": "マイナー手数料", "mining": "マイニング", "mining_active": "アクティブ", + "mining_address": "マイニングアドレス", "mining_address_copied": "マイニングアドレスをコピーしました", "mining_all_time": "全期間", "mining_already_saved": "プールURLは既に保存済みです", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "テスト中", "mining_benchmark_tooltip": "このCPUに最適なスレッド数を検出", "mining_block_copied": "ブロックハッシュをコピーしました", + "mining_card_click_to_shield": "クリックすると成熟した報酬を今すぐシールドします。", + "mining_card_tooltip": "ソロマイニング報酬はマイニング(透明、R…)アドレスに届きます。これらのアドレスは支払いを受け取れません。報酬は成熟すると自動的にシールドされます。", "mining_chart_1m_ago": "1分前", "mining_chart_5m_ago": "5分前", "mining_chart_now": "現在", @@ -1283,6 +1286,7 @@ "mining_payout_address": "支払いアドレス", "mining_payout_foreign": "⚠ この支払いアドレスは現在のウォレットに含まれていません — マイニング報酬が別のウォレットに送られます。ウォレットを切り替えた場合は更新してください。", "mining_payout_invalid": "有効な DragonX アドレスではありません — 開始前に修正してください。さもないとマイニング報酬が失われます。", + "mining_payout_needs_shielded": "プールは通常のトランザクションで支払いますが、DragonX ではそれがマイニング(透明、R…)アドレスに届きません。支払い先にはシールドアドレス(zs で始まる)を使用してください。", "mining_payout_tooltip": "マイニング報酬の受取アドレス", "mining_pool": "プール", "mining_pool_fee": "手数料", @@ -1295,6 +1299,8 @@ "mining_refresh": "更新", "mining_remove": "削除", "mining_reset_defaults": "デフォルトにリセット", + "mining_rewards": "マイニング報酬", + "mining_rewards_unshielded": "未シールド", "mining_save_payout_address": "支払いアドレスを保存", "mining_save_pool_url": "プールURLを保存", "mining_saved_addresses": "保存済みアドレス:", @@ -1328,10 +1334,10 @@ "network_fee": "ネットワーク手数料", "network_hashrate": "ネットワークハッシュレート", "new": "+ 新規", + "new_mining_address": "新しいマイニングアドレス", + "new_mining_address_created": "新しいマイニングアドレスを作成しました", "new_shielded_created": "新しいシールドアドレスを作成しました", - "new_t_address": "新しいTアドレス", "new_t_transparent": "新しいtアドレス(透明)", - "new_transparent_created": "新しい透明アドレスを作成しました", "new_z_address": "新しいZアドレス", "new_z_shielded": "新しいzアドレス(シールド)", "no_addresses": "アドレスが見つかりません。上のボタンを使用して作成してください。", @@ -1696,6 +1702,8 @@ "send_from_this_address": "このアドレスから送金", "send_go_to_receive": "受信へ移動", "send_keep": "保持", + "send_mining_addr_blocked": "これはマイニング(透明)アドレスです。DragonX ではこのアドレスはマイニング報酬しか受け取れず、ネットワークはこのアドレスへの支払いを拒否します。受取人にシールドアドレス(zs で始まる)を依頼してください。", + "send_mining_addr_short": "マイニングアドレス — 支払いを受け取れません", "send_network_fee": "ネットワーク手数料", "send_no_balance": "残高なし", "send_no_recent": "最近の送信なし", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxIDをクリップボードにコピーしました", "send_txid_label": "TxID:%s", "send_valid_shielded": "有効なシールドアドレス", - "send_valid_transparent": "有効な透明アドレス", "send_wallet_empty": "ウォレットは空です", "send_yes_clear": "はい、クリア", "sender_balance": "送信者: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "実行中のノードを停止しますか?", "switch_stopnode_warn": "このウォレットが起動していないノードがすでに実行中です。", "syncing": "同期中...", - "t_address": "Tアドレス", "t_addresses": "Tアドレス", "test_connection": "テスト", "theme": "テーマ", @@ -1964,8 +1970,6 @@ "transfer_sent": "送金完了", "transfer_sent_desc": "送金がネットワークに送信されました。", "transfer_to": "送金先:", - "transparent": "透明", - "transparent_address": "トランスペアレントアドレス", "try_again": "再試行", "tt_addr_url": "ブロックエクスプローラーでアドレスを表示するためのベース URL", "tt_address_book": "クイック送信用の保存済みアドレスを管理", @@ -2037,6 +2041,7 @@ "tt_low_spec": "すべての重い視覚効果を無効化\\nホットキー:Ctrl+Shift+Down", "tt_merge": "複数の UTXO を一つのアドレスに統合", "tt_mine_idle": "システムがアイドル状態(キーボード/マウス入力なし)\\nのとき自動的にマイニングを開始", + "tt_new_mining_address": "ソロマイニング報酬用の透明(R…)アドレスを作成します。支払いは受け取れません。支払いにはシールドアドレスを共有してください。", "tt_noise": "グレインテクスチャ強度(0% = オフ、100% = 最大)", "tt_open_app_dir": "ObsidianDragon フォルダ(設定、テーマ、ログ)をファイルマネージャーで開く", "tt_open_data_dir": "ファイルマネージャーでウォレットとブロックチェーンデータのフォルダを開きます", diff --git a/res/lang/ko.json b/res/lang/ko.json index 2573d1b..953286f 100644 --- a/res/lang/ko.json +++ b/res/lang/ko.json @@ -25,6 +25,7 @@ "about_website": "웹사이트", "acrylic": "아크릴", "add": "추가", + "addr_type_mining": "채굴", "address": "주소", "address_book_add": "주소 추가", "address_book_add_new": "새로 추가", @@ -172,21 +173,20 @@ "balance_history_collecting": "잔액 내역 — 데이터 수집 중...", "balance_layout": "잔액 레이아웃", "balance_layout_switched": "레이아웃: %s", + "balance_mining_fmt": "채굴 보상: %.8f", "balance_mining_rate": "채굴 중 %s", "balance_shielded_fmt": "차폐: %.8f", "balance_syncing_pct": "동기화 중 %.1f%%", - "balance_transparent_fmt": "투명: %.8f", "baltab_market": "시세", "baltab_market_price_4dp": "시세: $%.4f", "baltab_market_price_8dp": "시세: $%.8f", + "baltab_mining_addresses_count": "채굴 주소 %d개", + "baltab_mining_amount": "채굴 보상 %.8f", "baltab_pct_change_24h": "%s%.1f%% 24시간", "baltab_pct_of_total_zaddr": "전체의 %.0f%% · Z-addr %d개", "baltab_shielded": "실드됨", "baltab_shielded_amount": "실드됨 %.8f", - "baltab_t_addresses_count": "T-address %d개", "baltab_total_balance": "총 잔액", - "baltab_transparent": "투명", - "baltab_transparent_amount": "투명 %.8f", "ban": "차단", "banned_peers": "차단된 피어", "block": "블록", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "이미지는 앱에 복사되어 원본이 이동해도 계속 사용할 수 있습니다.", "contact_avatar_remove": "제거", "contact_avatar_shielded": "보호", - "contact_avatar_transparent": "투명", + "contact_chip_mining": "채굴 전용", "contact_global": "모든 지갑에 표시(전역 연락처)", "contact_global_badge_tt": "전역 연락처 — 모든 지갑에서 표시됨", "contact_global_tt": "켜짐: 어떤 지갑을 불러오든 이 연락처가 계속 표시됩니다. 꺼짐: 현재 지갑에만 속합니다.", @@ -707,8 +707,8 @@ "export_tx_success": "거래 내보내기 성공", "export_tx_title": "거래를 CSV로 내보내기", "export_viewing_key": "조회 키 내보내기", + "failed_create_mining_address": "채굴 주소를 만들지 못했습니다", "failed_create_shielded": "차폐 주소 생성 실패", - "failed_create_transparent": "투명 주소 생성 실패", "faq": "FAQ", "faq_d_mgmt_1_a": "내장 노드는 지갑과 함께 자동으로 시작되고 적절한 시점에 중지되므로, 보통 직접 관리할 필요가 없습니다. 고급 제어 기능(데몬 재시작 포함)은 설정 > 노드 및 보안에 있습니다.", "faq_d_mgmt_1_q": "노드를 시작하거나 중지하려면 어떻게 하나요?", @@ -1226,6 +1226,7 @@ "miner_fee": "채굴 수수료", "mining": "채굴", "mining_active": "활성", + "mining_address": "채굴 주소", "mining_address_copied": "채굴 주소가 복사되었습니다", "mining_all_time": "전체 기간", "mining_already_saved": "풀 URL이 이미 저장되어 있습니다", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "테스트 중", "mining_benchmark_tooltip": "이 CPU에 최적의 스레드 수 찾기", "mining_block_copied": "블록 해시가 복사되었습니다", + "mining_card_click_to_shield": "클릭하면 성숙한 보상을 지금 차폐합니다.", + "mining_card_tooltip": "솔로 채굴 보상은 채굴(투명, R…) 주소로 들어옵니다. 이 주소는 결제를 받을 수 없습니다. 보상은 성숙하면 자동으로 차폐됩니다.", "mining_chart_1m_ago": "1분 전", "mining_chart_5m_ago": "5분 전", "mining_chart_now": "현재", @@ -1283,6 +1286,7 @@ "mining_payout_address": "지급 주소", "mining_payout_foreign": "⚠ 이 지급 주소는 현재 지갑에 없습니다 — 채굴한 보상이 다른 지갑으로 전송됩니다. 지갑을 전환했다면 주소를 업데이트하세요.", "mining_payout_invalid": "유효한 DragonX 주소가 아닙니다 — 시작하기 전에 수정하세요. 그렇지 않으면 채굴 보상이 사라집니다.", + "mining_payout_needs_shielded": "풀은 일반 트랜잭션으로 지급하는데, DragonX에서는 이것이 채굴(투명, R…) 주소에 도달할 수 없습니다. 지급 주소로 차폐 주소(zs로 시작)를 사용하세요.", "mining_payout_tooltip": "채굴 보상 수신 주소", "mining_pool": "풀", "mining_pool_fee": "수수료", @@ -1295,6 +1299,8 @@ "mining_refresh": "새로고침", "mining_remove": "제거", "mining_reset_defaults": "기본값으로 재설정", + "mining_rewards": "채굴 보상", + "mining_rewards_unshielded": "아직 차폐되지 않음", "mining_save_payout_address": "지급 주소 저장", "mining_save_pool_url": "풀 URL 저장", "mining_saved_addresses": "저장된 주소:", @@ -1328,10 +1334,10 @@ "network_fee": "네트워크 수수료", "network_hashrate": "네트워크 해시레이트", "new": "+ 새로 만들기", + "new_mining_address": "새 채굴 주소", + "new_mining_address_created": "새 채굴 주소를 만들었습니다", "new_shielded_created": "새 차폐 주소가 생성되었습니다", - "new_t_address": "새 T 주소", "new_t_transparent": "새 t 주소 (투명)", - "new_transparent_created": "새 투명 주소가 생성되었습니다", "new_z_address": "새 Z 주소", "new_z_shielded": "새 z 주소 (차폐)", "no_addresses": "주소가 없습니다. 위의 버튼을 사용하여 생성하세요.", @@ -1696,6 +1702,8 @@ "send_from_this_address": "이 주소에서 전송", "send_go_to_receive": "수신으로 이동", "send_keep": "유지", + "send_mining_addr_blocked": "채굴(투명) 주소입니다. DragonX에서 이런 주소는 채굴 보상만 받을 수 있으며, 네트워크가 이 주소로의 결제를 거부합니다. 받는 사람에게 차폐 주소(zs로 시작)를 요청하세요.", + "send_mining_addr_short": "채굴 주소 — 결제를 받을 수 없음", "send_network_fee": "네트워크 수수료", "send_no_balance": "잔액 없음", "send_no_recent": "최근 전송 없음", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxID가 클립보드에 복사되었습니다", "send_txid_label": "TxID: %s", "send_valid_shielded": "유효한 차폐 주소", - "send_valid_transparent": "유효한 투명 주소", "send_wallet_empty": "지갑이 비어 있습니다", "send_yes_clear": "예, 지우기", "sender_balance": "발신자: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "실행 중인 노드를 중지할까요?", "switch_stopnode_warn": "이 지갑이 시작하지 않은 노드가 이미 실행 중입니다.", "syncing": "동기화 중...", - "t_address": "T 주소", "t_addresses": "T 주소", "test_connection": "테스트", "theme": "테마", @@ -1964,8 +1970,6 @@ "transfer_sent": "이체 전송됨", "transfer_sent_desc": "이체가 네트워크에 제출되었습니다.", "transfer_to": "이체 대상:", - "transparent": "투명", - "transparent_address": "투명 주소", "try_again": "다시 시도", "tt_addr_url": "블록 탐색기에서 주소를 보기 위한 기본 URL", "tt_address_book": "빠른 전송을 위해 저장된 주소 관리", @@ -2037,6 +2041,7 @@ "tt_low_spec": "모든 고부하 시각 효과 비활성화\\n단축키: Ctrl+Shift+Down", "tt_merge": "여러 UTXO를 하나의 주소로 통합", "tt_mine_idle": "시스템이 유휴 상태(키보드/마우스 입력 없음)일 때\\n자동으로 채굴 시작", + "tt_new_mining_address": "솔로 채굴 보상용 투명(R…) 주소를 만듭니다. 결제는 받을 수 없으니, 결제용으로는 차폐 주소를 공유하세요.", "tt_noise": "그레인 텍스처 강도 (0% = 끔, 100% = 최대)", "tt_open_app_dir": "파일 관리자에서 ObsidianDragon 폴더(설정, 테마, 로그)를 엽니다", "tt_open_data_dir": "지갑 및 블록체인 데이터가 있는 폴더를 파일 탐색기에서 엽니다", diff --git a/res/lang/pt.json b/res/lang/pt.json index 75b862a..8e92e43 100644 --- a/res/lang/pt.json +++ b/res/lang/pt.json @@ -25,6 +25,7 @@ "about_website": "Website", "acrylic": "Acrílico", "add": "Adicionar", + "addr_type_mining": "Mineração", "address": "Endereço", "address_book_add": "Adicionar Endereço", "address_book_add_new": "Adicionar Novo", @@ -172,21 +173,20 @@ "balance_history_collecting": "Histórico de saldo — coletando dados...", "balance_layout": "Layout do Saldo", "balance_layout_switched": "Layout: %s", + "balance_mining_fmt": "Recompensas de mineração: %.8f", "balance_mining_rate": "Minerando %s", "balance_shielded_fmt": "Blindado: %.8f", "balance_syncing_pct": "Sincronizando %.1f%%", - "balance_transparent_fmt": "Transparente: %.8f", "baltab_market": "Mercado", "baltab_market_price_4dp": "Mercado: $%.4f", "baltab_market_price_8dp": "Mercado: $%.8f", + "baltab_mining_addresses_count": "%d endereços de mineração", + "baltab_mining_amount": "Recompensas de mineração %.8f", "baltab_pct_change_24h": "%s%.1f%% 24h", "baltab_pct_of_total_zaddr": "%.0f%% do total · %d Z-addr", "baltab_shielded": "Blindado", "baltab_shielded_amount": "Blindado %.8f", - "baltab_t_addresses_count": "%d T-addresses", "baltab_total_balance": "Saldo Total", - "baltab_transparent": "Transparente", - "baltab_transparent_amount": "Transparente %.8f", "ban": "Banir", "banned_peers": "Pares Banidos", "block": "Bloco", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "A imagem é copiada para o app para continuar disponível se o original for movido.", "contact_avatar_remove": "Remover", "contact_avatar_shielded": "Blindado", - "contact_avatar_transparent": "Transparente", + "contact_chip_mining": "Só mineração", "contact_global": "Mostrar em todas as carteiras (contato global)", "contact_global_badge_tt": "Contato global — visível em todas as carteiras", "contact_global_tt": "Ativado: este contato permanece visível em qualquer carteira que você carregar. Desativado: ele pertence apenas à carteira atual.", @@ -707,8 +707,8 @@ "export_tx_success": "Transações exportadas com sucesso", "export_tx_title": "Exportar Transações para CSV", "export_viewing_key": "Exportar Chave de Visualização", + "failed_create_mining_address": "Falha ao criar o endereço de mineração", "failed_create_shielded": "Falha ao criar endereço blindado", - "failed_create_transparent": "Falha ao criar endereço transparente", "faq": "Perguntas frequentes", "faq_d_mgmt_1_a": "O node incorporado inicia automaticamente com a carteira e para quando apropriado, então normalmente você não precisa gerenciá-lo manualmente. Os controles avançados (incluindo reiniciar o daemon) ficam em Configurações > Node e Segurança.", "faq_d_mgmt_1_q": "Como inicio ou paro o node?", @@ -1226,6 +1226,7 @@ "miner_fee": "Taxa de Minerador", "mining": "Mineração", "mining_active": "Ativo", + "mining_address": "Endereço de mineração", "mining_address_copied": "Endereço de mineração copiado", "mining_all_time": "Todo o Tempo", "mining_already_saved": "URL do pool já salva", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "Testando", "mining_benchmark_tooltip": "Encontrar o número ideal de threads para esta CPU", "mining_block_copied": "Hash do bloco copiado", + "mining_card_click_to_shield": "Clique para blindar agora as recompensas amadurecidas.", + "mining_card_tooltip": "As recompensas de mineração solo chegam aos seus endereços de mineração (transparentes, R…). Esses endereços não podem receber pagamentos. As recompensas são blindadas automaticamente quando amadurecem.", "mining_chart_1m_ago": "1m atrás", "mining_chart_5m_ago": "5m atrás", "mining_chart_now": "Agora", @@ -1283,6 +1286,7 @@ "mining_payout_address": "Endereço de Pagamento", "mining_payout_foreign": "⚠ Este endereço de pagamento não está na sua carteira atual — as recompensas mineradas iriam para uma carteira diferente. Atualize-o se você trocou de carteira.", "mining_payout_invalid": "Endereço DragonX inválido — corrija antes de iniciar, ou as recompensas de mineração serão perdidas.", + "mining_payout_needs_shielded": "Os pools pagam com transações comuns, que no DragonX não conseguem chegar a um endereço de mineração (transparente, R…). Use um endereço blindado (começa com zs) como endereço de pagamento.", "mining_payout_tooltip": "Endereço para receber recompensas de mineração", "mining_pool": "Pool", "mining_pool_fee": "Taxa", @@ -1295,6 +1299,8 @@ "mining_refresh": "Atualizar", "mining_remove": "Remover", "mining_reset_defaults": "Redefinir Padrões", + "mining_rewards": "Recompensas de mineração", + "mining_rewards_unshielded": "Ainda não blindadas", "mining_save_payout_address": "Salvar endereço de pagamento", "mining_save_pool_url": "Salvar URL do pool", "mining_saved_addresses": "Endereços Salvos:", @@ -1328,10 +1334,10 @@ "network_fee": "TAXA DA REDE", "network_hashrate": "Hashrate da Rede", "new": "+ Novo", + "new_mining_address": "Novo endereço de mineração", + "new_mining_address_created": "Novo endereço de mineração criado", "new_shielded_created": "Novo endereço blindado criado", - "new_t_address": "Novo Endereço T", "new_t_transparent": "Novo endereço t (Transparente)", - "new_transparent_created": "Novo endereço transparente criado", "new_z_address": "Novo Endereço Z", "new_z_shielded": "Novo endereço z (Blindado)", "no_addresses": "Nenhum endereço encontrado. Crie um usando os botões acima.", @@ -1696,6 +1702,8 @@ "send_from_this_address": "Enviar deste endereço", "send_go_to_receive": "Ir para Receber", "send_keep": "Manter", + "send_mining_addr_blocked": "Este é um endereço de mineração (transparente). No DragonX eles só podem receber recompensas de mineração — a rede rejeita pagamentos para eles. Peça ao destinatário um endereço blindado (começa com zs).", + "send_mining_addr_short": "Endereço de mineração — não pode receber pagamentos", "send_network_fee": "TAXA DA REDE", "send_no_balance": "Sem saldo", "send_no_recent": "Nenhum envio recente", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxID copiado para a área de transferência", "send_txid_label": "TxID: %s", "send_valid_shielded": "Endereço blindado válido", - "send_valid_transparent": "Endereço transparente válido", "send_wallet_empty": "Sua carteira está vazia", "send_yes_clear": "Sim, Limpar", "sender_balance": "Remetente: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "Parar o nó em execução?", "switch_stopnode_warn": "Já há um nó em execução que esta carteira não iniciou.", "syncing": "Sincronizando...", - "t_address": "Endereço T", "t_addresses": "Endereços T", "test_connection": "Testar", "theme": "Tema", @@ -1964,8 +1970,6 @@ "transfer_sent": "Transferência Enviada", "transfer_sent_desc": "Sua transferência foi enviada à rede.", "transfer_to": "Transferir para:", - "transparent": "Transparente", - "transparent_address": "Endereço Transparente", "try_again": "Tentar novamente", "tt_addr_url": "URL base para visualizar endereços em um explorador de blocos", "tt_address_book": "Gerenciar endereços salvos para envio rápido", @@ -2037,6 +2041,7 @@ "tt_low_spec": "Desativar todos os efeitos visuais pesados\\nAtalho: Ctrl+Shift+Down", "tt_merge": "Consolidar múltiplos UTXOs em um endereço", "tt_mine_idle": "Iniciar mineração automaticamente quando o\\nsistema estiver ocioso (sem entrada de teclado/mouse)", + "tt_new_mining_address": "Cria um endereço transparente (R…) para recompensas de mineração solo. Ele não pode receber pagamentos — compartilhe um endereço blindado para isso.", "tt_noise": "Intensidade de textura granulada (0% = desligado, 100% = máximo)", "tt_open_app_dir": "Abrir a pasta ObsidianDragon (configurações, temas, logs) no gerenciador de arquivos", "tt_open_data_dir": "Abrir a pasta com os dados da sua carteira e da blockchain no gerenciador de arquivos", diff --git a/res/lang/ru.json b/res/lang/ru.json index 4e6bb2a..fc7cb05 100644 --- a/res/lang/ru.json +++ b/res/lang/ru.json @@ -25,6 +25,7 @@ "about_website": "Веб-сайт", "acrylic": "Акрил", "add": "Добавить", + "addr_type_mining": "Майнинг", "address": "Адрес", "address_book_add": "Добавить адрес", "address_book_add_new": "Добавить новый", @@ -172,21 +173,20 @@ "balance_history_collecting": "История баланса — сбор данных...", "balance_layout": "Макет баланса", "balance_layout_switched": "Раскладка: %s", + "balance_mining_fmt": "Награды за майнинг: %.8f", "balance_mining_rate": "Майнинг %s", "balance_shielded_fmt": "Экранировано: %.8f", "balance_syncing_pct": "Синхронизация %.1f%%", - "balance_transparent_fmt": "Прозрачный: %.8f", "baltab_market": "Рынок", "baltab_market_price_4dp": "Рынок: $%.4f", "baltab_market_price_8dp": "Рынок: $%.8f", + "baltab_mining_addresses_count": "Адресов для майнинга: %d", + "baltab_mining_amount": "Награды за майнинг %.8f", "baltab_pct_change_24h": "%s%.1f%% за 24ч", "baltab_pct_of_total_zaddr": "%.0f%% от общего · %d Z-addr", "baltab_shielded": "Скрытый", "baltab_shielded_amount": "Скрытый %.8f", - "baltab_t_addresses_count": "%d T-адресов", "baltab_total_balance": "Общий баланс", - "baltab_transparent": "Прозрачный", - "baltab_transparent_amount": "Прозрачный %.8f", "ban": "Заблокировать", "banned_peers": "Заблокированные узлы", "block": "Блок", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "Изображение копируется в приложение, чтобы оставаться доступным, если оригинал переместят.", "contact_avatar_remove": "Удалить", "contact_avatar_shielded": "Защищённый", - "contact_avatar_transparent": "Прозрачный", + "contact_chip_mining": "Только майнинг", "contact_global": "Показывать во всех кошельках (глобальный контакт)", "contact_global_badge_tt": "Глобальный контакт — виден во всех кошельках", "contact_global_tt": "Вкл.: этот контакт остаётся видимым, какой бы кошелёк вы ни загрузили. Выкл.: он принадлежит только текущему кошельку.", @@ -707,8 +707,8 @@ "export_tx_success": "Транзакции успешно экспортированы", "export_tx_title": "Экспорт транзакций в CSV", "export_viewing_key": "Экспорт ключа просмотра", + "failed_create_mining_address": "Не удалось создать адрес для майнинга", "failed_create_shielded": "Не удалось создать экранированный адрес", - "failed_create_transparent": "Не удалось создать прозрачный адрес", "faq": "ЧаВо", "faq_d_mgmt_1_a": "Встроенный узел запускается автоматически вместе с кошельком и останавливается, когда это уместно, поэтому обычно управлять им вручную не нужно. Расширенные элементы управления (включая перезапуск демона) находятся в Настройки > Узел и безопасность.", "faq_d_mgmt_1_q": "Как запустить или остановить узел?", @@ -1226,6 +1226,7 @@ "miner_fee": "Комиссия майнера", "mining": "Майнинг", "mining_active": "Активен", + "mining_address": "Адрес для майнинга", "mining_address_copied": "Адрес майнинга скопирован", "mining_all_time": "За всё время", "mining_already_saved": "URL пула уже сохранён", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "Тестирование", "mining_benchmark_tooltip": "Найти оптимальное количество потоков для этого процессора", "mining_block_copied": "Хэш блока скопирован", + "mining_card_click_to_shield": "Нажмите, чтобы экранировать созревшие награды сейчас.", + "mining_card_tooltip": "Награды за соло-майнинг поступают на ваши адреса для майнинга (прозрачные, R…). Эти адреса не принимают платежи. Награды экранируются автоматически, когда созревают.", "mining_chart_1m_ago": "1м назад", "mining_chart_5m_ago": "5м назад", "mining_chart_now": "Сейчас", @@ -1283,6 +1286,7 @@ "mining_payout_address": "Адрес выплат", "mining_payout_foreign": "⚠ Этот адрес выплат отсутствует в вашем текущем кошельке — намайненные вознаграждения будут отправлены в другой кошелёк. Обновите его, если вы сменили кошелёк.", "mining_payout_invalid": "Недействительный адрес DragonX — исправьте перед запуском, иначе награды за майнинг будут потеряны.", + "mining_payout_needs_shielded": "Пулы выплачивают обычными транзакциями, которые в DragonX не могут дойти до адреса для майнинга (прозрачного, R…). Укажите экранированный адрес (начинается с zs) как адрес для выплат.", "mining_payout_tooltip": "Адрес для получения вознаграждений за майнинг", "mining_pool": "Пул", "mining_pool_fee": "Комиссия", @@ -1295,6 +1299,8 @@ "mining_refresh": "Обновить", "mining_remove": "Удалить", "mining_reset_defaults": "Сбросить настройки", + "mining_rewards": "Награды за майнинг", + "mining_rewards_unshielded": "Ещё не экранированы", "mining_save_payout_address": "Сохранить адрес выплат", "mining_save_pool_url": "Сохранить URL пула", "mining_saved_addresses": "Сохранённые адреса:", @@ -1328,10 +1334,10 @@ "network_fee": "СЕТЕВАЯ КОМИССИЯ", "network_hashrate": "Хешрейт сети", "new": "+ Новый", + "new_mining_address": "Новый адрес для майнинга", + "new_mining_address_created": "Новый адрес для майнинга создан", "new_shielded_created": "Создан новый экранированный адрес", - "new_t_address": "Новый T-адрес", "new_t_transparent": "Новый t-адрес (Прозрачный)", - "new_transparent_created": "Создан новый прозрачный адрес", "new_z_address": "Новый Z-адрес", "new_z_shielded": "Новый z-адрес (Экранированный)", "no_addresses": "Адреса не найдены. Создайте один, используя кнопки выше.", @@ -1696,6 +1702,8 @@ "send_from_this_address": "Отправить с этого адреса", "send_go_to_receive": "Перейти к получению", "send_keep": "Сохранить", + "send_mining_addr_blocked": "Это адрес для майнинга (прозрачный). В DragonX такие адреса могут получать только награды за майнинг — сеть отклоняет платежи на них. Попросите у получателя экранированный адрес (начинается с zs).", + "send_mining_addr_short": "Адрес для майнинга — не принимает платежи", "send_network_fee": "СЕТЕВАЯ КОМИССИЯ", "send_no_balance": "Нет баланса", "send_no_recent": "Нет недавних отправлений", @@ -1723,7 +1731,6 @@ "send_txid_copied": "TxID скопирован в буфер обмена", "send_txid_label": "TxID: %s", "send_valid_shielded": "Действительный экранированный адрес", - "send_valid_transparent": "Действительный прозрачный адрес", "send_wallet_empty": "Ваш кошелёк пуст", "send_yes_clear": "Да, очистить", "sender_balance": "Отправитель: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "Остановить запущенный узел?", "switch_stopnode_warn": "Уже запущен узел, который не был запущен этим кошельком.", "syncing": "Синхронизация...", - "t_address": "T-адрес", "t_addresses": "T-адреса", "test_connection": "Тест", "theme": "Тема", @@ -1964,8 +1970,6 @@ "transfer_sent": "Перевод отправлен", "transfer_sent_desc": "Ваш перевод отправлен в сеть.", "transfer_to": "Перевести на:", - "transparent": "Прозрачный", - "transparent_address": "Прозрачный адрес", "try_again": "Повторить", "tt_addr_url": "Базовый URL для просмотра адресов в обозревателе блоков", "tt_address_book": "Управление сохранёнными адресами для быстрой отправки", @@ -2037,6 +2041,7 @@ "tt_low_spec": "Отключить все тяжёлые визуальные эффекты\\nГорячая клавиша: Ctrl+Shift+Down", "tt_merge": "Объединить несколько UTXO в один адрес", "tt_mine_idle": "Автоматически начать майнинг при\\nпростое системы (нет ввода с клавиатуры/мыши)", + "tt_new_mining_address": "Создаёт прозрачный адрес (R…) для наград за соло-майнинг. Он не принимает платежи — для них сообщайте экранированный адрес.", "tt_noise": "Интенсивность зернистой текстуры (0% = выкл., 100% = максимум)", "tt_open_app_dir": "Открыть папку ObsidianDragon (настройки, темы, логи) в файловом менеджере", "tt_open_data_dir": "Открыть в файловом менеджере папку с данными кошелька и блокчейна", diff --git a/res/lang/zh.json b/res/lang/zh.json index 55de767..2946587 100644 --- a/res/lang/zh.json +++ b/res/lang/zh.json @@ -25,6 +25,7 @@ "about_website": "网站", "acrylic": "亚克力", "add": "添加", + "addr_type_mining": "挖矿", "address": "地址", "address_book_add": "添加地址", "address_book_add_new": "添加新地址", @@ -172,21 +173,20 @@ "balance_history_collecting": "余额历史——正在收集数据…", "balance_layout": "余额布局", "balance_layout_switched": "布局:%s", + "balance_mining_fmt": "挖矿奖励:%.8f", "balance_mining_rate": "挖矿中 %s", "balance_shielded_fmt": "屏蔽:%.8f", "balance_syncing_pct": "同步中 %.1f%%", - "balance_transparent_fmt": "透明:%.8f", "baltab_market": "市价", "baltab_market_price_4dp": "市价:$%.4f", "baltab_market_price_8dp": "市价:$%.8f", + "baltab_mining_addresses_count": "%d 个挖矿地址", + "baltab_mining_amount": "挖矿奖励 %.8f", "baltab_pct_change_24h": "%s%.1f%% 24小时", "baltab_pct_of_total_zaddr": "占总额 %.0f%% · %d 个 Z-addr", "baltab_shielded": "隐蔽", "baltab_shielded_amount": "隐蔽 %.8f", - "baltab_t_addresses_count": "%d 个 T-address", "baltab_total_balance": "总余额", - "baltab_transparent": "透明", - "baltab_transparent_amount": "透明 %.8f", "ban": "封禁", "banned_peers": "已封禁节点", "block": "区块", @@ -511,7 +511,7 @@ "contact_avatar_image_hint": "图片会复制到应用中,即使原文件移动也能保持可用。", "contact_avatar_remove": "移除", "contact_avatar_shielded": "隐蔽", - "contact_avatar_transparent": "透明", + "contact_chip_mining": "仅限挖矿", "contact_global": "在每个钱包中显示(全局联系人)", "contact_global_badge_tt": "全局联系人——在每个钱包中可见", "contact_global_tt": "开启:无论您加载哪个钱包,此联系人都保持可见。关闭:它仅属于当前钱包。", @@ -707,8 +707,8 @@ "export_tx_success": "交易导出成功", "export_tx_title": "导出交易到 CSV", "export_viewing_key": "导出查看密钥", + "failed_create_mining_address": "创建挖矿地址失败", "failed_create_shielded": "无法创建屏蔽地址", - "failed_create_transparent": "无法创建透明地址", "faq": "常见问题", "faq_d_mgmt_1_a": "内置节点会随钱包自动启动,并在适当时机停止,因此通常无需手动管理。高级控制选项(包括重启守护进程)位于 设置 > 节点与安全。", "faq_d_mgmt_1_q": "如何启动或停止节点?", @@ -1226,6 +1226,7 @@ "miner_fee": "矿工费", "mining": "挖矿", "mining_active": "活跃", + "mining_address": "挖矿地址", "mining_address_copied": "挖矿地址已复制", "mining_all_time": "所有时间", "mining_already_saved": "矿池 URL 已保存", @@ -1239,6 +1240,8 @@ "mining_benchmark_testing": "测试中", "mining_benchmark_tooltip": "为此 CPU 找到最佳线程数", "mining_block_copied": "区块哈希已复制", + "mining_card_click_to_shield": "点击立即屏蔽已成熟的奖励。", + "mining_card_tooltip": "单人挖矿奖励会发送到您的挖矿(透明,R…)地址。这些地址无法接收付款。奖励成熟后会自动屏蔽。", "mining_chart_1m_ago": "1分钟前", "mining_chart_5m_ago": "5分钟前", "mining_chart_now": "现在", @@ -1283,6 +1286,7 @@ "mining_payout_address": "支付地址", "mining_payout_foreign": "⚠ 此支付地址不在您当前的钱包中——挖矿奖励将进入另一个钱包。如果您切换过钱包,请更新它。", "mining_payout_invalid": "不是有效的 DragonX 地址——启动前请更正,否则挖矿奖励将丢失。", + "mining_payout_needs_shielded": "矿池使用普通交易付款,而在 DragonX 上普通交易无法到达挖矿(透明,R…)地址。请使用屏蔽地址(以 zs 开头)作为收款地址。", "mining_payout_tooltip": "接收挖矿奖励的地址", "mining_pool": "矿池", "mining_pool_fee": "费用", @@ -1295,6 +1299,8 @@ "mining_refresh": "刷新", "mining_remove": "移除", "mining_reset_defaults": "重置默认值", + "mining_rewards": "挖矿奖励", + "mining_rewards_unshielded": "尚未屏蔽", "mining_save_payout_address": "保存支付地址", "mining_save_pool_url": "保存矿池 URL", "mining_saved_addresses": "已保存地址:", @@ -1328,10 +1334,10 @@ "network_fee": "网络手续费", "network_hashrate": "全网算力", "new": "+ 新建", + "new_mining_address": "新建挖矿地址", + "new_mining_address_created": "已创建新的挖矿地址", "new_shielded_created": "新屏蔽地址已创建", - "new_t_address": "新 T 地址", "new_t_transparent": "新 t 地址(透明)", - "new_transparent_created": "新透明地址已创建", "new_z_address": "新 Z 地址", "new_z_shielded": "新 z 地址(屏蔽)", "no_addresses": "未找到地址。请使用上方按钮创建一个。", @@ -1696,6 +1702,8 @@ "send_from_this_address": "从此地址发送", "send_go_to_receive": "前往接收", "send_keep": "保留", + "send_mining_addr_blocked": "这是一个挖矿(透明)地址。在 DragonX 上,这类地址只能接收挖矿奖励——网络会拒绝向其付款。请向收款人索取屏蔽地址(以 zs 开头)。", + "send_mining_addr_short": "挖矿地址——无法接收付款", "send_network_fee": "网络手续费", "send_no_balance": "无余额", "send_no_recent": "没有最近的发送", @@ -1723,7 +1731,6 @@ "send_txid_copied": "交易ID 已复制到剪贴板", "send_txid_label": "TxID:%s", "send_valid_shielded": "有效的屏蔽地址", - "send_valid_transparent": "有效的透明地址", "send_wallet_empty": "您的钱包是空的", "send_yes_clear": "是,清除", "sender_balance": "发送方: %.8f → %.8f DRGX", @@ -1929,7 +1936,6 @@ "switch_stopnode_title": "停止正在运行的节点?", "switch_stopnode_warn": "已有一个并非由此钱包启动的节点正在运行。", "syncing": "同步中...", - "t_address": "T 地址", "t_addresses": "T 地址", "test_connection": "测试", "theme": "主题", @@ -1964,8 +1970,6 @@ "transfer_sent": "转账已发送", "transfer_sent_desc": "您的转账已提交到网络。", "transfer_to": "转账至:", - "transparent": "透明", - "transparent_address": "透明地址", "try_again": "重试", "tt_addr_url": "在区块浏览器中查看地址的基础 URL", "tt_address_book": "管理已保存的地址以快速发送", @@ -2037,6 +2041,7 @@ "tt_low_spec": "禁用所有重度视觉效果\\n快捷键:Ctrl+Shift+Down", "tt_merge": "将多个 UTXO 合并到一个地址", "tt_mine_idle": "系统空闲时自动开始挖矿\\n(无键盘/鼠标输入)", + "tt_new_mining_address": "创建一个用于单人挖矿奖励的透明(R…)地址。它无法接收付款——收款请提供屏蔽地址。", "tt_noise": "颗粒纹理强度(0% = 关闭,100% = 最大)", "tt_open_app_dir": "在文件管理器中打开 ObsidianDragon 文件夹(设置、主题、日志)", "tt_open_data_dir": "在文件管理器中打开包含您钱包和区块链数据的文件夹", diff --git a/scripts/add_missing_translations.py b/scripts/add_missing_translations.py index 191841f..b82a582 100644 --- a/scripts/add_missing_translations.py +++ b/scripts/add_missing_translations.py @@ -25,6 +25,176 @@ def load_english_keys(): # All translations for the 158 missing keys TRANSLATIONS = { + "send_mining_addr_short": { + "de": "Mining-Adresse – kann keine Zahlungen empfangen", + "es": "Dirección de minería: no puede recibir pagos", + "fr": "Adresse de minage — ne peut pas recevoir de paiements", + "pt": "Endereço de mineração — não pode receber pagamentos", + "ru": "Адрес для майнинга — не принимает платежи", + "zh": "挖矿地址——无法接收付款", + "ja": "マイニングアドレス — 支払いを受け取れません", + "ko": "채굴 주소 — 결제를 받을 수 없음", + }, + "send_mining_addr_blocked": { + "de": "Dies ist eine Mining-Adresse (transparent). Bei DragonX können solche Adressen nur Mining-Belohnungen empfangen – das Netzwerk lehnt Zahlungen an sie ab. Bitten Sie den Empfänger um eine abgeschirmte Adresse (sie beginnt mit zs).", + "es": "Esta es una dirección de minería (transparente). En DragonX solo pueden recibir recompensas de minería; la red rechaza los pagos a ellas. Pide al destinatario una dirección blindada (empieza por zs).", + "fr": "Ceci est une adresse de minage (transparente). Sur DragonX, elles ne peuvent recevoir que des récompenses de minage — le réseau refuse les paiements vers elles. Demandez au destinataire une adresse blindée (elle commence par zs).", + "pt": "Este é um endereço de mineração (transparente). No DragonX eles só podem receber recompensas de mineração — a rede rejeita pagamentos para eles. Peça ao destinatário um endereço blindado (começa com zs).", + "ru": "Это адрес для майнинга (прозрачный). В DragonX такие адреса могут получать только награды за майнинг — сеть отклоняет платежи на них. Попросите у получателя экранированный адрес (начинается с zs).", + "zh": "这是一个挖矿(透明)地址。在 DragonX 上,这类地址只能接收挖矿奖励——网络会拒绝向其付款。请向收款人索取屏蔽地址(以 zs 开头)。", + "ja": "これはマイニング(透明)アドレスです。DragonX ではこのアドレスはマイニング報酬しか受け取れず、ネットワークはこのアドレスへの支払いを拒否します。受取人にシールドアドレス(zs で始まる)を依頼してください。", + "ko": "채굴(투명) 주소입니다. DragonX에서 이런 주소는 채굴 보상만 받을 수 있으며, 네트워크가 이 주소로의 결제를 거부합니다. 받는 사람에게 차폐 주소(zs로 시작)를 요청하세요.", + }, + "mining_payout_needs_shielded": { + "de": "Pools zahlen mit gewöhnlichen Transaktionen aus, die bei DragonX keine Mining-Adresse (transparent, R…) erreichen können. Verwenden Sie eine abgeschirmte Adresse (sie beginnt mit zs) als Auszahlungsadresse.", + "es": "Los pools pagan con transacciones normales, que en DragonX no pueden llegar a una dirección de minería (transparente, R…). Usa una dirección blindada (empieza por zs) como dirección de pago.", + "fr": "Les pools paient avec des transactions ordinaires, qui ne peuvent pas atteindre une adresse de minage (transparente, R…) sur DragonX. Utilisez une adresse blindée (elle commence par zs) comme adresse de paiement.", + "pt": "Os pools pagam com transações comuns, que no DragonX não conseguem chegar a um endereço de mineração (transparente, R…). Use um endereço blindado (começa com zs) como endereço de pagamento.", + "ru": "Пулы выплачивают обычными транзакциями, которые в DragonX не могут дойти до адреса для майнинга (прозрачного, R…). Укажите экранированный адрес (начинается с zs) как адрес для выплат.", + "zh": "矿池使用普通交易付款,而在 DragonX 上普通交易无法到达挖矿(透明,R…)地址。请使用屏蔽地址(以 zs 开头)作为收款地址。", + "ja": "プールは通常のトランザクションで支払いますが、DragonX ではそれがマイニング(透明、R…)アドレスに届きません。支払い先にはシールドアドレス(zs で始まる)を使用してください。", + "ko": "풀은 일반 트랜잭션으로 지급하는데, DragonX에서는 이것이 채굴(투명, R…) 주소에 도달할 수 없습니다. 지급 주소로 차폐 주소(zs로 시작)를 사용하세요.", + }, + "new_mining_address": { + "de": "Neue Mining-Adresse", + "es": "Nueva dirección de minería", + "fr": "Nouvelle adresse de minage", + "pt": "Novo endereço de mineração", + "ru": "Новый адрес для майнинга", + "zh": "新建挖矿地址", + "ja": "新しいマイニングアドレス", + "ko": "새 채굴 주소", + }, + "tt_new_mining_address": { + "de": "Erstellt eine transparente Adresse (R…) für Solo-Mining-Belohnungen. Sie kann keine Zahlungen empfangen – teilen Sie dafür eine abgeschirmte Adresse.", + "es": "Crea una dirección transparente (R…) para recompensas de minería en solitario. No puede recibir pagos; para eso comparte una dirección blindada.", + "fr": "Crée une adresse transparente (R…) pour les récompenses de minage en solo. Elle ne peut pas recevoir de paiements — partagez une adresse blindée pour cela.", + "pt": "Cria um endereço transparente (R…) para recompensas de mineração solo. Ele não pode receber pagamentos — compartilhe um endereço blindado para isso.", + "ru": "Создаёт прозрачный адрес (R…) для наград за соло-майнинг. Он не принимает платежи — для них сообщайте экранированный адрес.", + "zh": "创建一个用于单人挖矿奖励的透明(R…)地址。它无法接收付款——收款请提供屏蔽地址。", + "ja": "ソロマイニング報酬用の透明(R…)アドレスを作成します。支払いは受け取れません。支払いにはシールドアドレスを共有してください。", + "ko": "솔로 채굴 보상용 투명(R…) 주소를 만듭니다. 결제는 받을 수 없으니, 결제용으로는 차폐 주소를 공유하세요.", + }, + "mining_address": { + "de": "Mining-Adresse", + "es": "Dirección de minería", + "fr": "Adresse de minage", + "pt": "Endereço de mineração", + "ru": "Адрес для майнинга", + "zh": "挖矿地址", + "ja": "マイニングアドレス", + "ko": "채굴 주소", + }, + "addr_type_mining": { + "de": "Mining", + "es": "Minería", + "fr": "Minage", + "pt": "Mineração", + "ru": "Майнинг", + "zh": "挖矿", + "ja": "マイニング", + "ko": "채굴", + }, + "mining_rewards": { + "de": "Mining-Belohnungen", + "es": "Recompensas de minería", + "fr": "Récompenses de minage", + "pt": "Recompensas de mineração", + "ru": "Награды за майнинг", + "zh": "挖矿奖励", + "ja": "マイニング報酬", + "ko": "채굴 보상", + }, + "mining_rewards_unshielded": { + "de": "Noch nicht abgeschirmt", + "es": "Aún sin blindar", + "fr": "Pas encore blindées", + "pt": "Ainda não blindadas", + "ru": "Ещё не экранированы", + "zh": "尚未屏蔽", + "ja": "未シールド", + "ko": "아직 차폐되지 않음", + }, + "baltab_mining_addresses_count": { + "de": "%d Mining-Adressen", + "es": "%d direcciones de minería", + "fr": "%d adresses de minage", + "pt": "%d endereços de mineração", + "ru": "Адресов для майнинга: %d", + "zh": "%d 个挖矿地址", + "ja": "マイニングアドレス %d 件", + "ko": "채굴 주소 %d개", + }, + "baltab_mining_amount": { + "de": "Mining-Belohnungen %.8f", + "es": "Recompensas de minería %.8f", + "fr": "Récompenses de minage %.8f", + "pt": "Recompensas de mineração %.8f", + "ru": "Награды за майнинг %.8f", + "zh": "挖矿奖励 %.8f", + "ja": "マイニング報酬 %.8f", + "ko": "채굴 보상 %.8f", + }, + "balance_mining_fmt": { + "de": "Mining-Belohnungen: %.8f", + "es": "Recompensas de minería: %.8f", + "fr": "Récompenses de minage : %.8f", + "pt": "Recompensas de mineração: %.8f", + "ru": "Награды за майнинг: %.8f", + "zh": "挖矿奖励:%.8f", + "ja": "マイニング報酬:%.8f", + "ko": "채굴 보상: %.8f", + }, + "mining_card_tooltip": { + "de": "Solo-Mining-Belohnungen gehen an Ihre Mining-Adressen (transparent, R…). Diese Adressen können keine Zahlungen empfangen. Belohnungen werden automatisch abgeschirmt, sobald sie gereift sind.", + "es": "Las recompensas de minería en solitario llegan a tus direcciones de minería (transparentes, R…). Esas direcciones no pueden recibir pagos. Las recompensas se blindan automáticamente cuando maduran.", + "fr": "Les récompenses de minage en solo arrivent sur vos adresses de minage (transparentes, R…). Ces adresses ne peuvent pas recevoir de paiements. Les récompenses sont blindées automatiquement une fois arrivées à maturité.", + "pt": "As recompensas de mineração solo chegam aos seus endereços de mineração (transparentes, R…). Esses endereços não podem receber pagamentos. As recompensas são blindadas automaticamente quando amadurecem.", + "ru": "Награды за соло-майнинг поступают на ваши адреса для майнинга (прозрачные, R…). Эти адреса не принимают платежи. Награды экранируются автоматически, когда созревают.", + "zh": "单人挖矿奖励会发送到您的挖矿(透明,R…)地址。这些地址无法接收付款。奖励成熟后会自动屏蔽。", + "ja": "ソロマイニング報酬はマイニング(透明、R…)アドレスに届きます。これらのアドレスは支払いを受け取れません。報酬は成熟すると自動的にシールドされます。", + "ko": "솔로 채굴 보상은 채굴(투명, R…) 주소로 들어옵니다. 이 주소는 결제를 받을 수 없습니다. 보상은 성숙하면 자동으로 차폐됩니다.", + }, + "mining_card_click_to_shield": { + "de": "Klicken, um gereifte Belohnungen jetzt abzuschirmen.", + "es": "Haz clic para blindar ahora las recompensas maduras.", + "fr": "Cliquez pour blinder dès maintenant les récompenses arrivées à maturité.", + "pt": "Clique para blindar agora as recompensas amadurecidas.", + "ru": "Нажмите, чтобы экранировать созревшие награды сейчас.", + "zh": "点击立即屏蔽已成熟的奖励。", + "ja": "クリックすると成熟した報酬を今すぐシールドします。", + "ko": "클릭하면 성숙한 보상을 지금 차폐합니다.", + }, + "contact_chip_mining": { + "de": "Nur Mining", + "es": "Solo minería", + "fr": "Minage seul", + "pt": "Só mineração", + "ru": "Только майнинг", + "zh": "仅限挖矿", + "ja": "マイニング専用", + "ko": "채굴 전용", + }, + "failed_create_mining_address": { + "de": "Mining-Adresse konnte nicht erstellt werden", + "es": "No se pudo crear la dirección de minería", + "fr": "Impossible de créer l'adresse de minage", + "pt": "Falha ao criar o endereço de mineração", + "ru": "Не удалось создать адрес для майнинга", + "zh": "创建挖矿地址失败", + "ja": "マイニングアドレスを作成できませんでした", + "ko": "채굴 주소를 만들지 못했습니다", + }, + "new_mining_address_created": { + "de": "Neue Mining-Adresse erstellt", + "es": "Nueva dirección de minería creada", + "fr": "Nouvelle adresse de minage créée", + "pt": "Novo endereço de mineração criado", + "ru": "Новый адрес для майнинга создан", + "zh": "已创建新的挖矿地址", + "ja": "新しいマイニングアドレスを作成しました", + "ko": "새 채굴 주소를 만들었습니다", + }, "appx_node_busy_try_later": { "de": "Der Node ist mit einer langen Aufgabe beschäftigt (etwa dem Neuaufbau der Note-Witnesses). Versuchen Sie es erneut, wenn sie abgeschlossen ist; ein Stoppen jetzt könnte diese Arbeit von vorn beginnen lassen.", "es": "El nodo está ocupado terminando una tarea larga (como reconstruir los testigos de notas). Vuelve a intentarlo cuando termine; detenerlo ahora podría hacer que empiece ese trabajo de nuevo.", diff --git a/src/app_network.cpp b/src/app_network.cpp index fccf893..c3992a1 100644 --- a/src/app_network.cpp +++ b/src/app_network.cpp @@ -2689,10 +2689,12 @@ void App::startPoolMining(int threads) // Validate the payout address at EVERY start entry point (manual Start button, idle auto-start, thread // scaling) — not just the UI gate — since a stale/hand-edited/wrong-chain address here silently loses // mining rewards. (M-01) worker_name IS the pool login the rewards are credited to (see below). + // A pool pays with ordinary transactions, so only a shielded address can be paid (private chain). if (!cfg.worker_name.empty() && cfg.worker_name != "x" && !util::isValidRecipientAddress(cfg.worker_name)) { - ui::Notifications::instance().error( - "Pool payout address is not a valid DragonX address — mining not started."); + ui::Notifications::instance().error(util::isTransparentAddress(cfg.worker_name) + ? TR("mining_payout_needs_shielded") + : "Pool payout address is not a valid DragonX address — mining not started."); return; } // The algo follows the pool: official pools use their own algo (pool.dragonx.cc diff --git a/src/app_sweep.cpp b/src/app_sweep.cpp index b7309f3..13e8c17 100644 --- a/src/app_sweep.cpp +++ b/src/app_sweep.cpp @@ -588,6 +588,11 @@ void App::buildSweepCatalog() [](App& a) { a.state_.connected = false; a.state_.encryption_state_known = false; }, [](App& a) { a.applyHealthyDemoState(); }); + // A mining (transparent) address as the recipient: shown as unpayable, Send disabled. + add("send-mining-recipient", ui::NavPage::Send, + [](App& a) { ui::SweepSetSendRecipient(&a, "R9NXAVJezHiBnT3ijTpg3JUZre7PxhJWti"); }, + [](App& a) { ui::SweepSetSendRecipient(&a, nullptr); }); + // Send-confirm popup (state lives in send_tab statics → driven via a debug hook). add("popup-send-confirm", ui::NavPage::Send, [](App& a) { ui::SweepShowSendConfirm(&a, true); }, diff --git a/src/ui/windows/address_label_dialog.h b/src/ui/windows/address_label_dialog.h index e8f9a17..2218539 100644 --- a/src/ui/windows/address_label_dialog.h +++ b/src/ui/windows/address_label_dialog.h @@ -71,7 +71,7 @@ public: // Address preview Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), - s_isZ ? TR("shielded_address") : TR("transparent_address")); + s_isZ ? TR("shielded_address") : TR("mining_address")); ImGui::Spacing(); { std::string display = s_address; diff --git a/src/ui/windows/balance_components.cpp b/src/ui/windows/balance_components.cpp index 523f7dc..b35dc9e 100644 --- a/src/ui/windows/balance_components.cpp +++ b/src/ui/windows/balance_components.cpp @@ -213,12 +213,13 @@ void RenderSharedAddressList(App* app, float listH, float availW, }); } ImGui::SameLine(); - if (TactileButton(TR("new_t_address"), ImVec2(buttonWidth, 0), + if (TactileButton(TR("new_mining_address"), ImVec2(buttonWidth, 0), S.resolveFont(addrBtn.font.empty() ? "button" : addrBtn.font))) { app->createNewTAddress([](const std::string& addr) { DEBUG_LOGF("Created new t-address: %s\n", addr.c_str()); }); } + if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_new_mining_address")); ImGui::EndDisabled(); ImGui::Dummy(ImVec2(0, Layout::spacingXs())); @@ -402,13 +403,13 @@ void RenderSharedAddressList(App* app, float listH, float availW, const auto& target = rows[s_dropTargetIdx]; material::Tooltip("%s\n%s\n\n%s %s", truncateAddress(addr.address, 32).c_str(), - row.isZ ? TR("shielded") : TR("transparent"), + row.isZ ? TR("shielded") : TR("addr_type_mining"), TR("transfer_to"), truncateAddress(target.info->address, 32).c_str()); } else { material::Tooltip("%s\n%s\n\n%s", truncateAddress(addr.address, 32).c_str(), - row.isZ ? TR("shielded") : TR("transparent"), + row.isZ ? TR("shielded") : TR("addr_type_mining"), TR("address_reorder_hint")); } } @@ -440,7 +441,8 @@ void RenderSharedAddressList(App* app, float listH, float availW, if (s_dragActive && s_dragIdx != row_idx && material::IsRectHovered(rowPos, rowEnd)) { s_dropTargetIdx = row_idx; const float relY = rowH > 0.0f ? (mousePos.y - rowPos.y) / rowH : 0.5f; - s_dropMode = (relY < 0.30f || relY > 0.70f) ? 1 : 0; + // A mining (transparent) address can't be paid, so it is never a transfer target: reorder only. + s_dropMode = (!row.isZ || relY < 0.30f || relY > 0.70f) ? 1 : 0; if (s_dropMode == 0) { // Transfer: highlight the whole target row. dl->AddRectFilled(rowPos, rowEnd, WithAlpha(Primary(), 40), 4.0f * dp); @@ -542,7 +544,7 @@ void RenderSharedAddressList(App* app, float listH, float availW, // ---- Type label (first line) ---- float labelX = rowLayout.labelX; { - const char* typeLabel = row.isZ ? TR("shielded") : TR("transparent"); + const char* typeLabel = row.isZ ? TR("shielded") : TR("addr_type_mining"); const char* hiddenTag = row.hidden ? TR("hidden_tag") : ""; const char* miningTag = row.mining ? TR("mining_tag") : ""; char typeBuf[64]; @@ -682,7 +684,7 @@ void RenderSharedAddressList(App* app, float listH, float availW, KeyExportDialog::show(addr.address, KeyExportDialog::KeyType::Viewing); } if (ImGui::MenuItem(TR("show_qr_code"))) - QRPopupDialog::show(addr.address, row.isZ ? TR("z_address") : TR("t_address")); + QRPopupDialog::show(addr.address, row.isZ ? TR("z_address") : TR("mining_address")); ImGui::Separator(); if (row.hidden) { if (ImGui::MenuItem(TR("restore_address"))) diff --git a/src/ui/windows/balance_tab.cpp b/src/ui/windows/balance_tab.cpp index c46deb0..68e704c 100644 --- a/src/ui/windows/balance_tab.cpp +++ b/src/ui/windows/balance_tab.cpp @@ -12,6 +12,7 @@ #include "qr_popup_dialog.h" #include "address_label_dialog.h" #include "address_transfer_dialog.h" +#include "shield_dialog.h" #include "send_tab.h" #include "../../app.h" #include "../../config/settings.h" @@ -531,7 +532,7 @@ static void RenderBalanceClassic(App* app) float cy = cMin.y + cardPadLg; dl->AddText(ovFont, ovFont->LegacySize, ImVec2(cx, cy), - OnSurfaceMedium(), TR("transparent")); + OnSurfaceMedium(), TR("mining_rewards")); cy += ovFont->LegacySize + ovGap; snprintf(buf, sizeof(buf), "%.8f", s_dispTransparent); @@ -543,18 +544,24 @@ static void RenderBalanceClassic(App* app) OnSurfaceMedium(), DRAGONX_TICKER); cy += sub1->LegacySize + valGap; - snprintf(buf, sizeof(buf), TR("baltab_t_addresses_count"), - (int)state.t_addresses.size()); + // Rewards waiting at a mining address: say so, and let a click shield them now. + const bool unshielded = s_dispTransparent > 0.0; + if (unshielded) snprintf(buf, sizeof(buf), "%s", TR("mining_rewards_unshielded")); + else snprintf(buf, sizeof(buf), TR("baltab_mining_addresses_count"), (int)state.t_addresses.size()); dl->AddText(capFont, capFont->LegacySize, ImVec2(cx, cy), - OnSurfaceDisabled(), buf); + unshielded ? amberCol : OnSurfaceDisabled(), buf); - // Hover glow + click to Receive + // Hover glow + explain; click shields waiting rewards (else opens Receive) if (material::IsRectHovered(cMin, cMax)) { dl->AddRect(cMin, cMax, IM_COL32(255, 255, 255, (int)S.drawElement("tabs.balance", "hover-glow-alpha").sizeOr(40.0f)), cardSpec.rounding, 0, S.drawElement("tabs.balance", "hover-glow-thickness").sizeOr(1.5f) * dp); ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - if (ImGui::IsMouseClicked(0)) - app->setCurrentPage(NavPage::Receive); + material::Tooltip("%s%s%s", TR("mining_card_tooltip"), unshielded ? "\n\n" : "", + unshielded ? TR("mining_card_click_to_shield") : ""); + if (ImGui::IsMouseClicked(0)) { + if (unshielded) ShieldDialog::showShieldCoinbase(); + else app->setCurrentPage(NavPage::Receive); + } } } @@ -803,7 +810,7 @@ static void RenderBalanceDonut(App* app) { // Transparent legend dl->AddCircleFilled(ImVec2(legendX + 5 * dp, legendY + capFont->LegacySize * 0.5f), legendDotR, Warning()); - snprintf(buf, sizeof(buf), TR("baltab_transparent_amount"), s_dispTransparent); + snprintf(buf, sizeof(buf), TR("baltab_mining_amount"), s_dispTransparent); dl->AddText(capFont, capFont->LegacySize, ImVec2(legendX + legendXOff, legendY), Warning(), buf); legendY += capFont->LegacySize + legendSectionGap; @@ -976,7 +983,7 @@ static void RenderBalanceConsolidated(App* app) { // Transparent bar float transX = cardMin.x + pad * 2 + halfW; barY = divY + Layout::spacingSm(); - std::string transLabelUpper = TR("transparent"); + std::string transLabelUpper = TR("mining_rewards"); std::transform(transLabelUpper.begin(), transLabelUpper.end(), transLabelUpper.begin(), [](unsigned char c){ return (char)std::toupper(c); }); dl->AddText(ovFont, ovFont->LegacySize, ImVec2(transX, barY), Warning(), transLabelUpper.c_str()); @@ -1100,7 +1107,7 @@ static void RenderBalanceDashboard(App* app) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return (char)std::toupper(c); }); return s; }; - std::string lblShielded = upperTR("shielded"), lblTransparent = upperTR("transparent"); + std::string lblShielded = upperTR("shielded"), lblTransparent = upperTR("mining_rewards"); std::string lblQuickSend = upperTR("quick_send"), lblQuickReceive = upperTR("quick_receive"); TileInfo tiles[4] = { @@ -1240,7 +1247,7 @@ static void RenderBalanceVerticalStack(App* app) { RowInfo rowInfos[4] = { {TR("baltab_total_balance"), ICON_MD_ACCOUNT_BALANCE_WALLET, S.resolveColor("var(--accent-total)", OnSurface()), s_dispTotal, 1.0f}, {TR("baltab_shielded"), ICON_MD_SHIELD, S.resolveColor("var(--accent-shielded)", Success()), s_dispShielded, shieldRatio}, - {TR("baltab_transparent"), ICON_MD_CIRCLE, S.resolveColor("var(--accent-transparent)", Warning()), s_dispTransparent, transRatio}, + {TR("mining_rewards"), ICON_MD_CIRCLE, S.resolveColor("var(--accent-transparent)", Warning()), s_dispTransparent, transRatio}, {TR("baltab_market"), ICON_MD_TRENDING_UP, S.resolveColor("var(--accent-action)", Primary()), state.market.price_usd, 0.0f}, }; @@ -1437,7 +1444,7 @@ static void RenderBalanceVertical2x2(App* app) { // Row 1: Market (left), Transparent (right) { {TR("baltab_market"), ICON_MD_TRENDING_UP, S.resolveColor("var(--accent-action)", Primary()), state.market.price_usd, 0.0f, true, false}, - {TR("baltab_transparent"), ICON_MD_CIRCLE, S.resolveColor("var(--accent-transparent)", Warning()), s_dispTransparent, transRatio, false, true}, + {TR("mining_rewards"), ICON_MD_CIRCLE, S.resolveColor("var(--accent-transparent)", Warning()), s_dispTransparent, transRatio, false, true}, }, }; @@ -1696,7 +1703,7 @@ static void RenderBalanceShield(App* app) { std::string shieldLabelUpper = TR("shielded"); std::transform(shieldLabelUpper.begin(), shieldLabelUpper.end(), shieldLabelUpper.begin(), [](unsigned char c){ return (char)std::toupper(c); }); - std::string transLabelUpper = TR("transparent"); + std::string transLabelUpper = TR("mining_rewards"); std::transform(transLabelUpper.begin(), transLabelUpper.end(), transLabelUpper.begin(), [](unsigned char c){ return (char)std::toupper(c); }); dl->AddText(ovFont, ovFont->LegacySize, ImVec2(infoX, infoY), Success(), shieldLabelUpper.c_str()); @@ -1855,7 +1862,7 @@ static void RenderBalanceTimeline(App* app) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return (char)std::toupper(c); }); return s; }; - std::string cShielded = upperTR("shielded"), cTransparent = upperTR("transparent"), cMarket = upperTR("market"); + std::string cShielded = upperTR("shielded"), cTransparent = upperTR("mining_rewards"), cMarket = upperTR("market"); SumCard cards[3] = { {cShielded.c_str(), Success(), s_dispShielded, false}, {cTransparent.c_str(), Warning(), s_dispTransparent, false}, @@ -2137,7 +2144,7 @@ static void RenderBalanceMinimal(App* app) { snprintf(buf, sizeof(buf), TR("balance_shielded_fmt"), s_dispShielded); Type().textColored(TypeStyle::Caption, Success(), buf); ImGui::SameLine(0, Layout::spacingLg()); - snprintf(buf, sizeof(buf), TR("balance_transparent_fmt"), s_dispTransparent); + snprintf(buf, sizeof(buf), TR("balance_mining_fmt"), s_dispTransparent); Type().textColored(TypeStyle::Caption, Warning(), buf); // USD value diff --git a/src/ui/windows/contacts_tab.cpp b/src/ui/windows/contacts_tab.cpp index 43d9770..95a58d1 100644 --- a/src/ui/windows/contacts_tab.cpp +++ b/src/ui/windows/contacts_tab.cpp @@ -624,7 +624,7 @@ void RenderContactsTab(App* app) float cy = origin.y + std::max(0.0f, (a.y - blockH) * 0.42f); float cx = origin.x + a.x * 0.5f; struct Chip { bool sh; const char* lbl; }; - Chip chips[2] = { { true, TR("contact_avatar_shielded") }, { false, TR("contact_avatar_transparent") } }; + Chip chips[2] = { { true, TR("contact_avatar_shielded") }, { false, TR("contact_chip_mining") } }; for (int i = 0; i < 2; i++) { float ccx = cx + (i == 0 ? -(chipR + chipGap * 0.5f) : (chipR + chipGap * 0.5f)); ImVec2 cc(ccx, cy + chipR); diff --git a/src/ui/windows/market_tab.cpp b/src/ui/windows/market_tab.cpp index d4b8a2c..c82660f 100644 --- a/src/ui/windows/market_tab.cpp +++ b/src/ui/windows/market_tab.cpp @@ -624,7 +624,7 @@ static void pfDrawAddressSection(App* app) // Funded (right). Select-all is deferred so it applies to the freshly-filtered set below. bool selAllClicked = false; { - const char* flabels[3] = { TR("portfolio_select_all"), TR("shielded"), TR("transparent") }; + const char* flabels[3] = { TR("portfolio_select_all"), TR("shielded"), TR("addr_type_mining") }; const char* selLbl = TR("portfolio_select_shown"); const char* clrLbl = TR("portfolio_clear_sel"); ImGuiStyle& st = ImGui::GetStyle(); diff --git a/src/ui/windows/mining_controls.cpp b/src/ui/windows/mining_controls.cpp index 0a318b6..044960e 100644 --- a/src/ui/windows/mining_controls.cpp +++ b/src/ui/windows/mining_controls.cpp @@ -957,7 +957,9 @@ void RenderMiningControls(App* app, const WalletState& state, const MiningInfo& else if (poolBlockedBySolo) material::Tooltip("%s", TR("mining_stop_solo_for_pool")); else if (poolNeedsPayout) - material::Tooltip("%s", TR("mining_pool_needs_payout_tooltip")); + material::Tooltip("%s", util::isTransparentAddress(poolPayoutStr) + ? TR("mining_payout_needs_shielded") + : TR("mining_pool_needs_payout_tooltip")); else material::Tooltip("%s", isMiningActive ? TR("stop_mining") : TR("start_mining")); } diff --git a/src/ui/windows/mining_mode_toggle.cpp b/src/ui/windows/mining_mode_toggle.cpp index 198a640..8b73e10 100644 --- a/src/ui/windows/mining_mode_toggle.cpp +++ b/src/ui/windows/mining_mode_toggle.cpp @@ -413,7 +413,10 @@ void RenderMiningModeToggle(App* app, const WalletState& state, const MiningInfo if (currentWorkerStr.empty()) { material::Tooltip("%s", TR("mining_generate_z_address_hint")); } else if (currentWorkerStr != "x" && !util::isValidRecipientAddress(currentWorkerStr)) { - material::Tooltip("%s", TR("mining_payout_invalid")); // block start below too (M-01) + // Block start below too (M-01). A pool pays with ordinary transactions, which can't reach + // a transparent (mining) address on this private chain: say so rather than "invalid". + material::Tooltip("%s", util::isTransparentAddress(currentWorkerStr) + ? TR("mining_payout_needs_shielded") : TR("mining_payout_invalid")); } else { material::Tooltip("%s", TR("mining_payout_tooltip")); } diff --git a/src/ui/windows/receive_tab.cpp b/src/ui/windows/receive_tab.cpp index 7e8bbef..301f557 100644 --- a/src/ui/windows/receive_tab.cpp +++ b/src/ui/windows/receive_tab.cpp @@ -325,10 +325,10 @@ static void RenderAddressDropdown(App* app, float width) { app->createNewTAddress([](const std::string& addr) { s_generating_address = false; if (addr.empty()) - Notifications::instance().error(TR("failed_create_transparent")); + Notifications::instance().error(TR("failed_create_mining_address")); else { s_pending_select_address = addr; - Notifications::instance().success(TR("new_transparent_created")); + Notifications::instance().success(TR("new_mining_address_created")); } }); } diff --git a/src/ui/windows/send_tab.cpp b/src/ui/windows/send_tab.cpp index 8766eb4..f2c0a1b 100644 --- a/src/ui/windows/send_tab.cpp +++ b/src/ui/windows/send_tab.cpp @@ -693,6 +693,14 @@ static void RenderTxProgress(ImDrawList* dl, float x, float y, float w, // ============================================================================ // Confirmation dialog // ============================================================================ +void SweepSetSendRecipient(App* app, const char* to) { + (void)app; + std::snprintf(s_from_address, sizeof(s_from_address), "%s", + to ? "zs1demoprimaryshieldedaddressforuisweep000000000000000000000000000" : ""); + std::snprintf(s_to_address, sizeof(s_to_address), "%s", to ? to : ""); + s_amount = to ? 1.0 : 0.0; +} + void SweepShowSendConfirm(App* app, bool show) { (void)app; if (show) { @@ -975,7 +983,7 @@ static bool RenderZeroBalanceCTA(App* app, ImDrawList* dl, float width) { // Action buttons (Send + Clear + Undo) // ============================================================================ static void RenderActionButtons(App* app, float width, float vScale, - bool is_valid_address, double available, + bool is_valid_address, bool is_mining_addr, double available, const char* suffix = "") { auto& S = schema::UI(); const float dp = Layout::dpiScale(); @@ -1027,6 +1035,8 @@ static void RenderActionButtons(App* app, float width, float vScale, material::Tooltip("%s", TR("send_tooltip_syncing")); else if (s_from_address[0] == '\0') material::Tooltip("%s", TR("send_tooltip_select_source")); + else if (is_mining_addr) + material::Tooltip("%s", TR("send_mining_addr_blocked")); else if (!is_valid_address) material::Tooltip("%s", TR("send_tooltip_invalid_address")); else if (s_amount <= 0) @@ -1255,8 +1265,10 @@ void RenderSendTab(App* app) double available = GetAvailableBalance(app); bool is_valid_z = IsValidShieldedAddr(s_to_address); + // A transparent address is a mining address: it only ever receives mining rewards, and the network + // rejects a payment to it (DragonX is a private chain). Recognise it, but never send to it. bool is_valid_t = IsValidTransparentAddr(s_to_address); - bool is_valid_address = is_valid_z || is_valid_t; + bool is_valid_address = is_valid_z; float sectionGap = Layout::spacingXl() * vScale; char buf[128]; @@ -1365,7 +1377,9 @@ void RenderSendTab(App* app) if (vz) Type().textColored(TypeStyle::Caption, Success(), TR("send_valid_shielded")); else - Type().textColored(TypeStyle::Caption, Warning(), TR("send_valid_transparent")); + Type().textColored(TypeStyle::Caption, Error(), TR("send_mining_addr_short")); + if (vt && ImGui::IsItemHovered()) + material::Tooltip("%s", TR("send_mining_addr_blocked")); } else if (!checkPreview) { ImGui::SameLine(); Type().textColored(TypeStyle::Caption, Error(), TR("invalid_address")); @@ -1405,7 +1419,8 @@ void RenderSendTab(App* app) trimmed.erase(trimmed.begin()); while (!trimmed.empty() && (trimmed.back() == ' ' || trimmed.back() == '\n' || trimmed.back() == '\r' || trimmed.back() == '\t')) trimmed.pop_back(); - bool looksValid = dragonx::util::isValidRecipientAddress(trimmed); + // Preview any address, a mining one too: once pasted, the field explains why it can't be paid. + bool looksValid = dragonx::util::isDragonXAddress(trimmed); if (looksValid && s_to_address[0] == '\0') { s_preview_text = trimmed; s_paste_previewing = true; @@ -1626,7 +1641,7 @@ void RenderSendTab(App* app) ImGui::Dummy(ImVec2(0, innerGap * 0.5f)); // ---- ACTION BUTTONS (full width) ---- - RenderActionButtons(app, innerW, vScale, is_valid_address, available, "##main"); + RenderActionButtons(app, innerW, vScale, is_valid_address, is_valid_t, available, "##main"); // Add bottom padding ImGui::Dummy(ImVec2(0, pad * vScale)); diff --git a/src/ui/windows/send_tab.h b/src/ui/windows/send_tab.h index 248bd29..c034e96 100644 --- a/src/ui/windows/send_tab.h +++ b/src/ui/windows/send_tab.h @@ -30,6 +30,8 @@ void RenderSendConfirmPopup(App* app); * the only way an external driver (the full UI sweep) can reveal it. Fires no send. */ void SweepShowSendConfirm(App* app, bool show); +// UI sweep: put `to` (nullptr: clear) in the recipient field, e.g. a mining address to show it can't be paid. +void SweepSetSendRecipient(App* app, const char* to); /** * @brief Pre-fill the "from" address in the send tab diff --git a/src/util/address_validation.cpp b/src/util/address_validation.cpp index 6f3d6b6..f725053 100644 --- a/src/util/address_validation.cpp +++ b/src/util/address_validation.cpp @@ -164,10 +164,22 @@ bool isShieldedAddress(const std::string& s) || hrp == "zregtestsapling"; // regtest } -bool isValidRecipientAddress(const std::string& s) +bool isDragonXAddress(const std::string& s) { return isTransparentAddress(s) || isShieldedAddress(s); } +bool isValidRecipientAddress(const std::string& s) +{ + return isShieldedAddress(s); +} + +RecipientKind classifyRecipient(const std::string& s) +{ + if (isShieldedAddress(s)) return RecipientKind::Shielded; + if (isTransparentAddress(s)) return RecipientKind::MiningOnly; + return RecipientKind::Invalid; +} + } // namespace util } // namespace dragonx diff --git a/src/util/address_validation.h b/src/util/address_validation.h index ee3b365..48542a1 100644 --- a/src/util/address_validation.h +++ b/src/util/address_validation.h @@ -45,8 +45,18 @@ bool isTransparentAddress(const std::string& s); // with a valid Bech32 checksum. Distinguishes a payment address from a viewing key (e.g. "zivks…"). bool isShieldedAddress(const std::string& s); -// True if `s` is any address a payment can be sent to (transparent or shielded). +// True if `s` is a DragonX address of either kind (transparent or shielded) — "is this an address at all". +bool isDragonXAddress(const std::string& s); + +// True if `s` is an address a payment can be sent to. DragonX is a private chain (-ac_private=1): consensus +// rejects any non-coinbase output to a transparent address, so only a shielded address can be paid — sends, +// payment requests and pool payouts included. A transparent address only ever receives mining rewards. bool isValidRecipientAddress(const std::string& s); +// What sending to `s` would mean: a shielded address (payable), a mining address (transparent: valid, but +// it can only receive mining rewards, so a payment to it is rejected), or not an address. +enum class RecipientKind { Invalid, Shielded, MiningOnly }; +RecipientKind classifyRecipient(const std::string& s); + } // namespace util } // namespace dragonx diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index c6b0d58..4ef0736 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -1031,9 +1031,7 @@ void I18n::loadBuiltinEnglish() strings_["copied"] = "Copied!"; strings_["hidden_tag"] = " (hidden)"; strings_["z_address"] = "Z-Address"; - strings_["t_address"] = "T-Address"; strings_["shielded_address"] = "Shielded Address"; - strings_["transparent_address"] = "Transparent Address"; strings_["label_placeholder"] = "e.g. Savings, Mining..."; strings_["choose_icon"] = "Choose Icon"; strings_["clear_icon"] = "Clear Icon"; @@ -1169,7 +1167,6 @@ void I18n::loadBuiltinEnglish() // Balance Tab strings_["summary"] = "Summary"; strings_["shielded"] = "Shielded"; - strings_["transparent"] = "Transparent"; strings_["total"] = "Total"; strings_["unconfirmed"] = "Unconfirmed"; strings_["recent_transactions"] = "RECENT TRANSACTIONS"; @@ -1180,7 +1177,6 @@ void I18n::loadBuiltinEnglish() strings_["privacy_low"] = "Low privacy — shield funds"; strings_["balance_history_collecting"] = "Balance history — collecting data..."; strings_["balance_shielded_fmt"] = "Shielded: %.8f"; - strings_["balance_transparent_fmt"] = "Transparent: %.8f"; strings_["total_balance_label"] = "Total Balance"; strings_["balance_syncing_pct"] = "Syncing %.1f%%"; strings_["balance_mining_rate"] = "Mining %s"; @@ -1194,7 +1190,6 @@ void I18n::loadBuiltinEnglish() strings_["t_addresses"] = "T-Addresses"; strings_["no_addresses"] = "No addresses found. Create one using the buttons above."; strings_["new_z_address"] = "New Z-Address"; - strings_["new_t_address"] = "New T-Address"; strings_["type"] = "Type"; strings_["address"] = "Address"; strings_["copy_address"] = "Copy Full Address"; @@ -1792,7 +1787,6 @@ void I18n::loadBuiltinEnglish() strings_["contact_avatar_image"] = "Image"; strings_["contact_avatar_badge_hint"] = "The badge is chosen automatically from the address type."; strings_["contact_avatar_shielded"] = "Shielded"; - strings_["contact_avatar_transparent"] = "Transparent"; strings_["contact_avatar_choose"] = "Choose image\xE2\x80\xA6"; strings_["contact_avatar_remove"] = "Remove"; strings_["contact_avatar_image_hint"] = "The image is copied into the app so it stays available if the original moves."; @@ -2170,6 +2164,23 @@ void I18n::loadBuiltinEnglish() strings_["mining_payout_address"] = "Payout Address"; strings_["mining_payout_tooltip"] = "Address to receive mining rewards"; strings_["mining_payout_invalid"] = "Not a valid DragonX address — fix it before starting, or mining rewards are lost."; + strings_["send_mining_addr_short"] = "Mining address — can't be paid"; + strings_["send_mining_addr_blocked"] = "This is a mining (transparent) address. On DragonX these can only receive mining rewards — the network rejects payments to them. Ask the recipient for a shielded address (it starts with zs)."; + strings_["mining_payout_needs_shielded"] = "Pools pay out with ordinary transactions, which can't reach a mining (transparent, R…) address on DragonX. Use a shielded address (it starts with zs) as your payout address."; + strings_["new_mining_address"] = "New mining address"; + strings_["tt_new_mining_address"] = "Creates a transparent (R…) address for solo-mining rewards. It can't receive payments — share a shielded address for those."; + strings_["mining_address"] = "Mining address"; + strings_["addr_type_mining"] = "Mining"; + strings_["mining_rewards"] = "Mining rewards"; + strings_["mining_rewards_unshielded"] = "Not yet shielded"; + strings_["baltab_mining_addresses_count"] = "%d mining addresses"; + strings_["baltab_mining_amount"] = "Mining rewards %.8f"; + strings_["balance_mining_fmt"] = "Mining rewards: %.8f"; + strings_["mining_card_tooltip"] = "Solo-mining rewards arrive at your mining (transparent, R…) addresses. Those addresses can't receive payments. Rewards are shielded automatically once they mature."; + strings_["mining_card_click_to_shield"] = "Click to shield matured rewards now."; + strings_["contact_chip_mining"] = "Mining only"; + strings_["failed_create_mining_address"] = "Failed to create mining address"; + strings_["new_mining_address_created"] = "New mining address created"; strings_["mining_est_daily_pool_sub"] = "rough solo-equivalent, before pool fee"; strings_["mining_generate_z_address_hint"] = "Generate a Z address in the Receive tab to use as your payout address"; strings_["mining_pool_needs_payout_tooltip"] = "Enter a payout address first (generate a Z address)"; @@ -2388,9 +2399,7 @@ void I18n::loadBuiltinEnglish() strings_["click_copy_uri"] = "Click to copy URI"; strings_["generating"] = "Generating"; strings_["failed_create_shielded"] = "Failed to create shielded address"; - strings_["failed_create_transparent"] = "Failed to create transparent address"; strings_["new_shielded_created"] = "New shielded address created"; - strings_["new_transparent_created"] = "New transparent address created"; strings_["payment_request_copied"] = "Payment request copied"; strings_["payment_uri_copied"] = "Payment URI copied"; @@ -2453,7 +2462,6 @@ void I18n::loadBuiltinEnglish() strings_["send_txid_copied"] = "TxID copied to clipboard"; strings_["send_txid_label"] = "TxID: %s"; strings_["send_valid_shielded"] = "Valid shielded address"; - strings_["send_valid_transparent"] = "Valid transparent address"; strings_["send_wallet_empty"] = "Your wallet is empty"; strings_["send_yes_clear"] = "Yes, Clear"; @@ -2708,15 +2716,12 @@ void I18n::loadBuiltinEnglish() // balance_tab.cpp strings_["baltab_shielded_amount"] = "Shielded %.8f"; - strings_["baltab_transparent_amount"] = "Transparent %.8f"; strings_["baltab_market_price_4dp"] = "Market: $%.4f"; strings_["baltab_market_price_8dp"] = "Market: $%.8f"; strings_["baltab_pct_of_total_zaddr"] = "%.0f%% of total · %d Z-addr"; - strings_["baltab_t_addresses_count"] = "%d T-addresses"; strings_["baltab_pct_change_24h"] = "%s%.1f%% 24h"; strings_["baltab_total_balance"] = "Total Balance"; strings_["baltab_shielded"] = "Shielded"; - strings_["baltab_transparent"] = "Transparent"; strings_["baltab_market"] = "Market"; // settings_window.cpp diff --git a/tests/test_phase4.cpp b/tests/test_phase4.cpp index 0a6e3d6..89bce63 100644 --- a/tests/test_phase4.cpp +++ b/tests/test_phase4.cpp @@ -4410,21 +4410,10 @@ void testChooseDaemonStatus() EXPECT_TRUE(chooseDaemonStatus(false, false, idle) == DaemonStatusKind::Launching); // not bound yet } -// S10: every string added by the daemon-stop work exists in English and in all 8 languages, with the same -// printf arguments (a mismatch is rejected at runtime and would fall back to English, or worse). -void testDaemonStopStringsTranslated() +// Every key exists in English and in all 8 languages, with the same printf arguments (a mismatch is rejected +// at runtime and falls back to English, or worse). +static void expectKeysTranslated(const std::vector& keys) { - const char* keys[] = { - "shutdown_leave_running", "shutdown_leave_running_tip", "shutdown_kill_node", "shutdown_kill_node_tip", - "shutdown_kill_confirm_title", "shutdown_kill_confirm_msg", "shutdown_kill_confirm_yes", - "shutdown_stop_asking", "shutdown_stop_queued", "shutdown_stop_delivered", "shutdown_stop_cpu_suffix", - "shutdown_stop_idle", "node_busy_rebuild_title", "node_busy_rebuild_desc", "node_busy_rebuild_reading", - "node_busy_rebuild_extending", "node_busy_replay_title", "node_busy_replay_desc", "node_busy_rpc_title", - "node_busy_rpc_desc", "node_starting_title", "node_starting_busy_desc", "node_starting_launch_desc", - "sb_node_busy", "stopconfirm_rebuild_title", "stopconfirm_rebuild_body", "stopconfirm_busy_title", - "stopconfirm_busy_body", "stopconfirm_stop_wait", "appx_daemon_reinstall_node_busy", "node_busy_running", - "appx_node_busy_try_later", "appx_node_not_stopped", - }; // printf conversions in order, "%%" excluded: what must survive translation. auto conversions = [](const std::string& s) { std::string sig; @@ -4451,6 +4440,34 @@ void testDaemonStopStringsTranslated() } } +// S10: every string added by the daemon-stop work. +void testDaemonStopStringsTranslated() +{ + expectKeysTranslated({ + "shutdown_leave_running", "shutdown_leave_running_tip", "shutdown_kill_node", "shutdown_kill_node_tip", + "shutdown_kill_confirm_title", "shutdown_kill_confirm_msg", "shutdown_kill_confirm_yes", + "shutdown_stop_asking", "shutdown_stop_queued", "shutdown_stop_delivered", "shutdown_stop_cpu_suffix", + "shutdown_stop_idle", "node_busy_rebuild_title", "node_busy_rebuild_desc", "node_busy_rebuild_reading", + "node_busy_rebuild_extending", "node_busy_replay_title", "node_busy_replay_desc", "node_busy_rpc_title", + "node_busy_rpc_desc", "node_starting_title", "node_starting_busy_desc", "node_starting_launch_desc", + "sb_node_busy", "stopconfirm_rebuild_title", "stopconfirm_rebuild_body", "stopconfirm_busy_title", + "stopconfirm_busy_body", "stopconfirm_stop_wait", "appx_daemon_reinstall_node_busy", "node_busy_running", + "appx_node_busy_try_later", "appx_node_not_stopped", + }); +} + +// Mining addresses: the strings that explain transparent addresses only receive mining rewards. +void testMiningAddressStringsTranslated() +{ + expectKeysTranslated({ + "send_mining_addr_short", "send_mining_addr_blocked", "mining_payout_needs_shielded", "new_mining_address", + "tt_new_mining_address", "mining_address", "addr_type_mining", "mining_rewards", "mining_rewards_unshielded", + "baltab_mining_addresses_count", "baltab_mining_amount", "balance_mining_fmt", "mining_card_tooltip", + "mining_card_click_to_shield", "contact_chip_mining", "failed_create_mining_address", + "new_mining_address_created", + }); +} + // S3: on Linux a node in its final shutdown phase reads comm "hush-shutoff"; its executable still says // dragonxd, so it must still count as running (it holds the datadir lock until it exits). void testDaemonProcessIdentity() @@ -7787,12 +7804,25 @@ void testAddressChecksumValidation() EXPECT_FALSE(isShieldedAddress(p2pkh)); EXPECT_TRUE(isShieldedAddress(zaddr)); EXPECT_FALSE(isTransparentAddress(zaddr)); - EXPECT_TRUE(isValidRecipientAddress(p2pkh)); - EXPECT_TRUE(isValidRecipientAddress(p2sh)); + // Both kinds are DragonX addresses, but only a shielded one can be paid: the chain is private, so + // consensus rejects a payment to a transparent address (it only ever receives mining rewards). + using dragonx::util::isDragonXAddress; + using dragonx::util::classifyRecipient; + using dragonx::util::RecipientKind; + EXPECT_TRUE(isDragonXAddress(p2pkh)); + EXPECT_TRUE(isDragonXAddress(p2sh)); + EXPECT_TRUE(isDragonXAddress(zaddr)); + EXPECT_FALSE(isValidRecipientAddress(p2pkh)); + EXPECT_FALSE(isValidRecipientAddress(p2sh)); EXPECT_TRUE(isValidRecipientAddress(zaddr)); + EXPECT_TRUE(classifyRecipient(zaddr) == RecipientKind::Shielded); + EXPECT_TRUE(classifyRecipient(p2pkh) == RecipientKind::MiningOnly); + EXPECT_TRUE(classifyRecipient(p2sh) == RecipientKind::MiningOnly); + EXPECT_TRUE(classifyRecipient("x") == RecipientKind::Invalid); + EXPECT_TRUE(classifyRecipient("zivks1qqqsyqcyq5rqwzqfpg9scrgwpugpzysn") == RecipientKind::Invalid); // A WIF spending key is NOT a recipient (33/34-byte payload, not 21); nor is a typo'd address. EXPECT_FALSE(isTransparentAddress("Up3W7uVYkLxCfH91APxjSpkkGBWJyBrm3tt1bCz64V5fpZK9ef3C")); - EXPECT_FALSE(isValidRecipientAddress("R9NXAVJezHiBnT3ijTpg3JUZre7PxhJWtX")); // flipped checksum char + EXPECT_FALSE(isDragonXAddress("R9NXAVJezHiBnT3ijTpg3JUZre7PxhJWtX")); // flipped checksum char EXPECT_FALSE(isValidRecipientAddress("")); } @@ -9213,6 +9243,7 @@ int main() testOutputSinceAcrossTrim(); testChooseDaemonStatus(); testDaemonStopStringsTranslated(); + testMiningAddressStringsTranslated(); #ifdef _WIN32 testWindowsStopNeverKillsForeignDaemon(); #endif