mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-11-17 09:47:36 +00:00
p2pool: add [Ping] into GUI, add [simple], add address regex check
This commit is contained in:
parent
22a03a6034
commit
9638f9dc5b
10 changed files with 633 additions and 378 deletions
147
Cargo.lock
generated
147
Cargo.lock
generated
|
@ -4,7 +4,7 @@ version = 3
|
|||
|
||||
[[package]]
|
||||
name = "Gupax"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arti-client",
|
||||
|
@ -15,7 +15,7 @@ dependencies = [
|
|||
"eframe",
|
||||
"egui",
|
||||
"egui_extras",
|
||||
"env_logger 0.9.1",
|
||||
"env_logger 0.9.3",
|
||||
"figment",
|
||||
"flate2",
|
||||
"hex-literal",
|
||||
|
@ -112,9 +112,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57e6e951cfbb2db8de1828d49073a113a29fd7117b1596caa781a258c7e38d72"
|
||||
checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom 0.2.8",
|
||||
|
@ -294,9 +294,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "asynchronous-codec"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690"
|
||||
checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-sink",
|
||||
|
@ -434,18 +434,18 @@ checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.12.1"
|
||||
version = "1.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
|
||||
checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck_derive"
|
||||
version = "1.2.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9"
|
||||
checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -487,9 +487,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "calloop"
|
||||
version = "0.10.1"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a22a6a8f622f797120d452c630b0ab12e1331a1a753e2039ce7868d4ac77b4ee"
|
||||
checksum = "595eb0438b3c6d262395fe30e6de9a61beb57ea56290b00a07f227fe6e20cbf2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nix 0.24.2",
|
||||
|
@ -506,9 +506,9 @@ checksum = "ceea694ffdf0118d2df95ace6fd9edfc6d27f88408d0d73b390f2d9e5699b3f2"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.74"
|
||||
version = "1.0.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
|
||||
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
@ -603,9 +603,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.0"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
|
||||
checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
|
@ -893,9 +893,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.80"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
|
||||
checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
|
@ -905,9 +905,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.80"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
|
||||
checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
|
@ -920,15 +920,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.80"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
|
||||
checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.80"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
|
||||
checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1187,9 +1187,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "educe"
|
||||
version = "0.4.19"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c07b7cc9cd8c08d10db74fca3b20949b9b6199725c04a0cce6d543496098fcac"
|
||||
checksum = "cb0188e3c3ba8df5753894d54461f0e39bc91741dc5b22e1c46999ec2c71f4e4"
|
||||
dependencies = [
|
||||
"enum-ordinalize",
|
||||
"proc-macro2",
|
||||
|
@ -1225,7 +1225,7 @@ version = "0.19.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc9fcd393c3daaaf5909008a1d948319d538b79c51871e4df0993260260a94e4"
|
||||
dependencies = [
|
||||
"ahash 0.8.0",
|
||||
"ahash 0.8.2",
|
||||
"epaint",
|
||||
"nohash-hasher",
|
||||
"tracing",
|
||||
|
@ -1297,9 +1297,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "enum-ordinalize"
|
||||
version = "3.1.11"
|
||||
version = "3.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2170fc0efee383079a8bdd05d6ea2a184d2a0f07a1c1dcabdb2fd5e9f24bc36c"
|
||||
checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
|
@ -1324,9 +1324,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.1"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272"
|
||||
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime 2.1.0",
|
||||
|
@ -1342,7 +1342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5ba04741be7f6602b1a1b28f1082cce45948a7032961c52814f8946b28493300"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"ahash 0.8.0",
|
||||
"ahash 0.8.2",
|
||||
"atomic_refcell",
|
||||
"bytemuck",
|
||||
"emath",
|
||||
|
@ -1983,9 +1983,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.20"
|
||||
version = "0.14.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
|
||||
checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
@ -2110,9 +2110,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.0"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
|
||||
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
|
@ -2211,9 +2211,9 @@ checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
|||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
|
@ -2221,9 +2221,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
|
||||
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
|
@ -2266,9 +2266,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lzma-sys"
|
||||
version = "0.1.19"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e06754c4acf47d49c727d5665ca9fb828851cda315ed3bd51edd148ef78a8772"
|
||||
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
@ -2292,9 +2292,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.5.7"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
|
||||
checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -2389,9 +2389,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.10"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
|
||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
|
@ -2623,9 +2623,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
|
@ -2652,15 +2652,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
|
@ -2964,14 +2955,14 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
|||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.6"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c"
|
||||
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"miniz_oxide 0.5.4",
|
||||
"miniz_oxide 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2991,9 +2982,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
|
@ -3171,9 +3162,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -3182,9 +3173,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.27"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
|
@ -3291,7 +3282,7 @@ dependencies = [
|
|||
"hashlink",
|
||||
"libsqlite3-sys",
|
||||
"smallvec",
|
||||
"time 0.3.16",
|
||||
"time 0.3.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3378,9 +3369,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
|
@ -3647,7 +3638,7 @@ dependencies = [
|
|||
"num-bigint",
|
||||
"num-traits",
|
||||
"thiserror",
|
||||
"time 0.3.16",
|
||||
"time 0.3.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3911,13 +3902,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca"
|
||||
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
|
@ -3931,9 +3920,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
|||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b"
|
||||
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
@ -4356,7 +4345,7 @@ dependencies = [
|
|||
"serde",
|
||||
"signature",
|
||||
"thiserror",
|
||||
"time 0.3.16",
|
||||
"time 0.3.17",
|
||||
"tor-basic-utils",
|
||||
"tor-checkable",
|
||||
"tor-circmgr",
|
||||
|
@ -4513,7 +4502,7 @@ dependencies = [
|
|||
"serde_with",
|
||||
"signature",
|
||||
"thiserror",
|
||||
"time 0.3.16",
|
||||
"time 0.3.17",
|
||||
"tinystr",
|
||||
"tor-bytes",
|
||||
"tor-cert",
|
||||
|
@ -5341,7 +5330,7 @@ dependencies = [
|
|||
"hmac",
|
||||
"pbkdf2",
|
||||
"sha1",
|
||||
"time 0.3.16",
|
||||
"time 0.3.17",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "Gupax"
|
||||
version = "0.1.0"
|
||||
authors = ["hinto-janaiyo <hinto-janaiyo@protonmail.com>"]
|
||||
version = "0.2.0"
|
||||
authors = ["hinto-janaiyo <hinto.janaiyo@protonmail.com>"]
|
||||
description = "GUI for P2Pool+XMRig"
|
||||
documentation = "https://github.com/hinto-janaiyo/gupax"
|
||||
edition = "2021"
|
||||
|
|
|
@ -88,11 +88,10 @@ https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e
|
|||
* A Monero node/wallet
|
||||
|
||||
## Build
|
||||
Windows/macOS/Linux:
|
||||
```
|
||||
cargo build --release
|
||||
```
|
||||
On macOS, if you want the binary to have an icon in `Finder`, you must install [`cargo-bundle`](https://github.com/burtonageo/cargo-bundle) and compile uwith:
|
||||
On macOS, if you want the binary to have an icon in `Finder`, you must install [`cargo-bundle`](https://github.com/burtonageo/cargo-bundle) and compile with:
|
||||
```
|
||||
cargo bundle --release
|
||||
```
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
| File/Folder | Purpose |
|
||||
|----------------|---------|
|
||||
| `constants.rs` | General constants needed in Gupax
|
||||
| `gupax.rs` | Impl for `Gupax` tab
|
||||
| `main.rs` | Struct/enum/impl for `App/Tab/State`, init functions, main function
|
||||
| `node.rs` | Struct/impl for Community Nodes
|
||||
| `p2pool.rs` | Impl for `P2Pool` tab
|
||||
| `state.rs` | Struct/impl for `gupax.toml`, the disk state. This holds the structs representing tabs with mutable state (Gupax/P2Pool/XMRig)
|
||||
| `status.rs` | Struct/impl for `Status` tab
|
||||
| `xmrig.rs` | Impl for `XMRig` tab
|
||||
| `ferris.rs` | Cute crab `--ferris`
|
||||
| `gupax.rs` | `Gupax` tab
|
||||
| `main.rs` | `App/Tab/State` + misc functions
|
||||
| `node.rs` | Community node feature
|
||||
| `p2pool.rs` | `P2Pool` tab
|
||||
| `state.rs` | `gupax.toml` config code. This holds the structs representing tabs with mutable state (Gupax/P2Pool/XMRig)
|
||||
| `status.rs` | `Status` tab
|
||||
| `update.rs` | Update code for the `Gupax` tab
|
||||
| `xmrig.rs` | `XMRig` tab
|
||||
|
||||
## Bootstrap
|
||||
This is how Gupax works internally when starting up, divided into 3 sections.
|
||||
|
|
|
@ -69,13 +69,19 @@ pub const GUPAX_SAVE_BEFORE_QUIT: &'static str = "Automatically save any changed
|
|||
pub const GUPAX_PATH_P2POOL: &'static str = "The location of the P2Pool binary, both absolute and relative paths are accepted";
|
||||
pub const GUPAX_PATH_XMRIG: &'static str = "The location of the XMRig binary, both absolute and relative paths are accepted";
|
||||
// P2Pool
|
||||
pub const P2POOL_MAIN: &'static str = "The P2Pool main-chain. This P2Pool finds shares faster, but has a higher difficulty. Suitable for miners with more than 50kH/s";
|
||||
pub const P2POOL_MINI: &'static str = "The P2Pool mini-chain. This P2Pool finds shares slower, but has a lower difficulty. Suitable for miners with less than 50kH/s";
|
||||
pub const P2POOL_MAIN: &'static str = "Use the P2Pool main-chain. This P2Pool finds shares faster, but has a higher difficulty. Suitable for miners with more than 50kH/s";
|
||||
pub const P2POOL_MINI: &'static str = "Use the P2Pool mini-chain. This P2Pool finds shares slower, but has a lower difficulty. Suitable for miners with less than 50kH/s";
|
||||
pub const P2POOL_OUT: &'static str = "How many out-bound peers (you connecting to others) to connect to?";
|
||||
pub const P2POOL_IN: &'static str = "How many in-bound peers (others connecting to you) to connect to?";
|
||||
pub const P2POOL_LOG: &'static str = "Verbosity of the console log";
|
||||
pub const P2POOL_COMMUNITY: &'static str = "Connect to a community trusted Monero node: This is convenient because you don't have to download the Monero blockchain but it comes at the cost of privacy";
|
||||
pub const P2POOL_MANUAL: &'static str = "Manually specify your own Monero node settings";
|
||||
pub const P2POOL_AUTO_NODE: &'static str = "Automatically ping the community Monero nodes at Gupax startup";
|
||||
pub const P2POOL_AUTO_SELECT: &'static str = "Automatically select the fastest community Monero node after pinging";
|
||||
pub const P2POOL_SELECT_FASTEST: &'static str = "Select the fastest community Monero node";
|
||||
pub const P2POOL_PING: &'static str = "Ping the built-in community Monero nodes";
|
||||
pub const P2POOL_ADDRESS: &'static str = "You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet for P2Pool mining; wallet addresses are public on P2Pool!";
|
||||
|
||||
// XMRig
|
||||
pub const XMRIG_P2POOL: &'static str = "Mine to your own P2Pool instance (localhost:3333)";
|
||||
pub const XMRIG_MANUAL: &'static str = "Manually specify where to mine to";
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
use std::path::Path;
|
||||
use crate::{App,State};
|
||||
use egui::WidgetType::Button;
|
||||
use egui::TextStyle::Monospace;
|
||||
use egui::RichText;
|
||||
use crate::constants::*;
|
||||
use crate::state::{Gupax,Version};
|
||||
use crate::update::*;
|
||||
|
@ -73,7 +74,7 @@ impl Gupax {
|
|||
ui.set_enabled(updating);
|
||||
let prog = *update.lock().unwrap().prog.lock().unwrap();
|
||||
let msg = format!("{}\n{}{}", *update.lock().unwrap().msg.lock().unwrap(), prog, "%");
|
||||
ui.add_sized([width, height*1.4], egui::Label::new(msg));
|
||||
ui.add_sized([width, height*1.4], egui::Label::new(RichText::text_style(RichText::new(msg), Monospace)));
|
||||
let height = height/2.0;
|
||||
if updating {
|
||||
ui.add_sized([width, height], egui::Spinner::new().size(height));
|
||||
|
|
211
src/main.rs
211
src/main.rs
|
@ -34,6 +34,9 @@ use eframe::{egui,NativeOptions};
|
|||
use log::*;
|
||||
use env_logger::{Builder,WriteStyle};
|
||||
|
||||
// Regex
|
||||
use regex::Regex;
|
||||
|
||||
// std
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
@ -64,9 +67,7 @@ pub struct App {
|
|||
tab: Tab, // What tab are we on?
|
||||
quit: bool, // Was the quit button clicked?
|
||||
quit_confirm: bool, // Was the quit confirmed?
|
||||
ping: bool, // Was the ping button clicked?
|
||||
pinging: Arc<Mutex<bool>>, // Is a ping in progress?
|
||||
node: Arc<Mutex<NodeStruct>>, // Data on community nodes
|
||||
ping: Arc<Mutex<Ping>>, // Ping data found in [node.rs]
|
||||
width: f32, // Top-level width
|
||||
height: f32, // Top-level height
|
||||
// State
|
||||
|
@ -88,9 +89,10 @@ pub struct App {
|
|||
dir: String, // Directory [Gupax] binary is in
|
||||
resolution: Vec2, // Frame resolution
|
||||
os: &'static str, // OS
|
||||
version: String, // Gupax version
|
||||
version: &'static str, // Gupax version
|
||||
name_version: String, // [Gupax vX.X.X]
|
||||
banner: RetainedImage, // Gupax banner image
|
||||
addr_regex: Regex, // [4.*] Monero Address Regex
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
@ -108,11 +110,9 @@ impl App {
|
|||
tab: Tab::default(),
|
||||
quit: false,
|
||||
quit_confirm: false,
|
||||
ping: false,
|
||||
pinging: Arc::new(Mutex::new(false)),
|
||||
ping: Arc::new(Mutex::new(Ping::new())),
|
||||
width: 1280.0,
|
||||
height: 720.0,
|
||||
node: Arc::new(Mutex::new(NodeStruct::default())),
|
||||
og: Arc::new(Mutex::new(State::default())),
|
||||
state: State::default(),
|
||||
update: Arc::new(Mutex::new(Update::new(String::new(), PathBuf::new(), PathBuf::new(), true))),
|
||||
|
@ -126,9 +126,10 @@ impl App {
|
|||
dir: "".to_string(),
|
||||
resolution: Vec2::new(1280.0, 720.0),
|
||||
os: OS,
|
||||
version: format!("{}", GUPAX_VERSION),
|
||||
version: GUPAX_VERSION,
|
||||
name_version: format!("Gupax {}", GUPAX_VERSION),
|
||||
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).expect("oops"),
|
||||
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).unwrap(),
|
||||
addr_regex: Regex::new("^4[A-Za-z1-9]+$").unwrap(),
|
||||
};
|
||||
// Apply arg state
|
||||
let mut app = parse_args(app);
|
||||
|
@ -188,21 +189,15 @@ fn init_text_styles(ctx: &egui::Context, width: f32) {
|
|||
let scale = width / 26.666;
|
||||
let mut style = (*ctx.style()).clone();
|
||||
style.text_styles = [
|
||||
// (Small, FontId::new(10.0, Proportional)),
|
||||
// (Body, FontId::new(25.0, Proportional)),
|
||||
// (Button, FontId::new(25.0, Proportional)),
|
||||
// (Monospace, FontId::new(25.0, Proportional)),
|
||||
// (Heading, FontId::new(30.0, Proportional)),
|
||||
// (Name("Tab".into()), FontId::new(50.0, Proportional)),
|
||||
// (Name("Bottom".into()), FontId::new(25.0, Proportional)),
|
||||
(Small, FontId::new(scale/3.0, Proportional)),
|
||||
(Body, FontId::new(scale/2.0, Proportional)),
|
||||
(Button, FontId::new(scale/2.0, Proportional)),
|
||||
(Monospace, FontId::new(scale/2.0, Proportional)),
|
||||
(Monospace, FontId::new(scale/2.0, egui::FontFamily::Monospace)),
|
||||
(Heading, FontId::new(scale/1.5, Proportional)),
|
||||
(Name("Tab".into()), FontId::new(scale*1.2, Proportional)),
|
||||
(Name("Bottom".into()), FontId::new(scale/2.0, Proportional)),
|
||||
].into();
|
||||
// style.visuals.selection.stroke = Stroke { width: 5.0, color: Color32::from_rgb(255, 255, 255) };
|
||||
// style.spacing.slider_width = scale;
|
||||
// style.spacing.text_edit_width = scale;
|
||||
// style.spacing.button_padding = Vec2::new(scale/2.0, scale/2.0);
|
||||
|
@ -211,6 +206,14 @@ fn init_text_styles(ctx: &egui::Context, width: f32) {
|
|||
ctx.request_repaint();
|
||||
}
|
||||
|
||||
//fn init_color(ctx: &egui::Context) {
|
||||
// let mut style = (*ctx.style()).clone();
|
||||
// style.visuals.widgets.inactive.fg_stroke.color = Color32::from_rgb(100, 100, 100);
|
||||
// style.visuals.selection.bg_fill = Color32::from_rgb(255, 125, 50);
|
||||
// style.visuals.selection.stroke = Stroke { width: 5.0, color: Color32::from_rgb(255, 255, 255) };
|
||||
// ctx.set_style(style);
|
||||
//}
|
||||
|
||||
fn init_logger() {
|
||||
// #[cfg(debug_assertions)]
|
||||
let filter = LevelFilter::Info;
|
||||
|
@ -395,6 +398,9 @@ impl eframe::App for App {
|
|||
// *-------*
|
||||
// | DEBUG |
|
||||
// *-------*
|
||||
// crate::node::ping();
|
||||
// std::process::exit(0);
|
||||
// init_color(ctx);
|
||||
|
||||
// This sets the top level Ui dimensions.
|
||||
// Used as a reference for other uis.
|
||||
|
@ -413,6 +419,11 @@ impl eframe::App for App {
|
|||
// contains Arc<Mutex>'s that cannot be compared easily.
|
||||
// They don't need to be compared anyway.
|
||||
let og = self.og.lock().unwrap().clone();
|
||||
// The [P2Pool Node] selection needs to be the same
|
||||
// for both [State] and [Og] because of [Auto-select]
|
||||
// Wrapping [node] within an [Arc<Mutex>] is a lot more work
|
||||
// so sending it into the [Ping] thread is not viable.
|
||||
self.state.p2pool.node = self.og.lock().unwrap().p2pool.node;
|
||||
if og.gupax != self.state.gupax || og.p2pool != self.state.p2pool || og.xmrig != self.state.xmrig {
|
||||
self.diff = true;
|
||||
} else {
|
||||
|
@ -503,10 +514,7 @@ impl eframe::App for App {
|
|||
ui.style_mut().override_text_style = Some(Name("Tab".into()));
|
||||
ui.style_mut().visuals.widgets.inactive.fg_stroke.color = Color32::from_rgb(100, 100, 100);
|
||||
ui.style_mut().visuals.selection.bg_fill = Color32::from_rgb(255, 120, 120);
|
||||
ui.style_mut().visuals.selection.stroke = Stroke {
|
||||
width: 5.0,
|
||||
color: Color32::from_rgb(255, 255, 255),
|
||||
};
|
||||
ui.style_mut().visuals.selection.stroke = Stroke { width: 5.0, color: Color32::from_rgb(255, 255, 255) };
|
||||
if ui.add_sized([width, height], egui::SelectableLabel::new(self.tab == Tab::About, "About")).clicked() { self.tab = Tab::About; }
|
||||
ui.separator();
|
||||
if ui.add_sized([width, height], egui::SelectableLabel::new(self.tab == Tab::Status, "Status")).clicked() { self.tab = Tab::Status; }
|
||||
|
@ -523,104 +531,113 @@ impl eframe::App for App {
|
|||
|
||||
// Bottom: app info + state/process buttons
|
||||
egui::TopBottomPanel::bottom("bottom").show(ctx, |ui| {
|
||||
let width = self.width/8.0;
|
||||
let height = self.height/18.0;
|
||||
ui.style_mut().override_text_style = Some(Name("Bottom".into()));
|
||||
ui.horizontal(|ui| {
|
||||
ui.group(|ui| {
|
||||
// [Gupax Version] + [OS] + [P2Pool on/off] + [XMRig on/off]
|
||||
let width = ((self.width/2.0)/4.0)-(SPACE*2.0);
|
||||
ui.add_sized([width, height], Label::new(&*self.name_version));
|
||||
ui.separator();
|
||||
ui.add_sized([width, height], Label::new(self.os));
|
||||
ui.separator();
|
||||
ui.add_sized([width/1.5, height], Label::new("P2Pool"));
|
||||
if self.p2pool {
|
||||
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(100, 230, 100))));
|
||||
ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(Color32::from_rgb(100, 230, 100))));
|
||||
} else {
|
||||
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(230, 50, 50))));
|
||||
ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(Color32::from_rgb(230, 50, 50))));
|
||||
}
|
||||
ui.separator();
|
||||
ui.add_sized([width/1.5, height], Label::new("XMRig"));
|
||||
if self.xmrig {
|
||||
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(100, 230, 100))));
|
||||
ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(Color32::from_rgb(100, 230, 100))));
|
||||
} else {
|
||||
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(230, 50, 50))));
|
||||
ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(Color32::from_rgb(230, 50, 50))));
|
||||
}
|
||||
});
|
||||
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::RIGHT), |ui| {
|
||||
ui.group(|ui| {
|
||||
if self.diff == false {
|
||||
ui.set_enabled(false)
|
||||
}
|
||||
let width = width / 2.0;
|
||||
if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() {
|
||||
self.og.lock().unwrap().gupax = self.state.gupax.clone();
|
||||
self.og.lock().unwrap().p2pool = self.state.p2pool.clone();
|
||||
self.og.lock().unwrap().xmrig = self.state.xmrig.clone();
|
||||
self.og.lock().unwrap().save();
|
||||
}
|
||||
if ui.add_sized([width, height], egui::Button::new("Reset")).on_hover_text("Reset changes").clicked() {
|
||||
self.state.gupax = self.og.lock().unwrap().gupax.clone();
|
||||
self.state.p2pool = self.og.lock().unwrap().p2pool.clone();
|
||||
self.state.xmrig = self.og.lock().unwrap().xmrig.clone();
|
||||
}
|
||||
});
|
||||
|
||||
let width = (ui.available_width() / 3.0) - 6.2;
|
||||
match self.tab {
|
||||
Tab::P2pool => {
|
||||
ui.group(|ui| {
|
||||
if self.p2pool {
|
||||
if ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart P2Pool").clicked() { self.p2pool = false; }
|
||||
if ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop P2Pool").clicked() { self.p2pool = false; }
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start P2Pool");
|
||||
});
|
||||
} else {
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart P2Pool");
|
||||
ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop P2Pool");
|
||||
});
|
||||
if ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start P2Pool").clicked() { self.p2pool = true; }
|
||||
}
|
||||
});
|
||||
}
|
||||
Tab::Xmrig => {
|
||||
ui.group(|ui| {
|
||||
if self.xmrig {
|
||||
if ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart XMRig").clicked() { self.xmrig = false; }
|
||||
if ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop XMRig").clicked() { self.xmrig = false; }
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start XMRig");
|
||||
});
|
||||
} else {
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart XMRig");
|
||||
ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop XMRig");
|
||||
});
|
||||
if ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start XMRig").clicked() { self.xmrig = true; }
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
// [Start/Stop/Restart] + [Simple/Advanced] + [Save/Reset]
|
||||
let width = (ui.available_width()/3.0)-(SPACE*3.0);
|
||||
ui.group(|ui| {
|
||||
if self.diff == false {
|
||||
ui.set_enabled(false)
|
||||
}
|
||||
let width = width / 2.0;
|
||||
if ui.add_sized([width, height], egui::Button::new("Reset")).on_hover_text("Reset changes").clicked() {
|
||||
self.state.gupax = self.og.lock().unwrap().gupax.clone();
|
||||
self.state.p2pool = self.og.lock().unwrap().p2pool.clone();
|
||||
self.state.xmrig = self.og.lock().unwrap().xmrig.clone();
|
||||
}
|
||||
if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() {
|
||||
self.og.lock().unwrap().gupax = self.state.gupax.clone();
|
||||
self.og.lock().unwrap().p2pool = self.state.p2pool.clone();
|
||||
self.og.lock().unwrap().xmrig = self.state.xmrig.clone();
|
||||
self.og.lock().unwrap().save();
|
||||
}
|
||||
});
|
||||
|
||||
match self.tab {
|
||||
Tab::P2pool => {
|
||||
ui.group(|ui| {
|
||||
let width = width / 1.5;
|
||||
if ui.add_sized([width, height], egui::SelectableLabel::new(!self.state.p2pool.simple, "Advanced")).clicked() {
|
||||
self.state.p2pool.simple = false;
|
||||
}
|
||||
ui.separator();
|
||||
if ui.add_sized([width, height], egui::SelectableLabel::new(self.state.p2pool.simple, "Simple")).clicked() {
|
||||
self.state.p2pool.simple = true;
|
||||
}
|
||||
});
|
||||
ui.group(|ui| {
|
||||
let width = (ui.available_width()/3.0)-5.0;
|
||||
if self.p2pool {
|
||||
if ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart P2Pool").clicked() { self.p2pool = false; }
|
||||
if ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop P2Pool").clicked() { self.p2pool = false; }
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start P2Pool");
|
||||
});
|
||||
} else {
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart P2Pool");
|
||||
ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop P2Pool");
|
||||
});
|
||||
if ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start P2Pool").clicked() { self.p2pool = true; }
|
||||
}
|
||||
});
|
||||
}
|
||||
Tab::Xmrig => {
|
||||
ui.group(|ui| {
|
||||
let width = width / 1.5;
|
||||
if ui.add_sized([width, height], egui::SelectableLabel::new(!self.state.xmrig.simple, "Advanced")).clicked() {
|
||||
self.state.xmrig.simple = false;
|
||||
}
|
||||
ui.separator();
|
||||
if ui.add_sized([width, height], egui::SelectableLabel::new(self.state.xmrig.simple, "Simple")).clicked() {
|
||||
self.state.xmrig.simple = true;
|
||||
}
|
||||
});
|
||||
ui.group(|ui| {
|
||||
let width = (ui.available_width()/3.0)-5.0;
|
||||
if self.xmrig {
|
||||
if ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart XMRig").clicked() { self.xmrig = false; }
|
||||
if ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop XMRig").clicked() { self.xmrig = false; }
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start XMRig");
|
||||
});
|
||||
} else {
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart XMRig");
|
||||
ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop XMRig");
|
||||
});
|
||||
if ui.add_sized([width, height], egui::Button::new("⏺")).on_hover_text("Start XMRig").clicked() { self.xmrig = true; }
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// If ping was pressed, start thread
|
||||
if self.ping {
|
||||
self.ping = false;
|
||||
self.pinging = Arc::new(Mutex::new(true));
|
||||
let node_clone = Arc::clone(&self.node);
|
||||
let pinging_clone = Arc::clone(&self.pinging);
|
||||
thread::spawn(move|| {
|
||||
let result = NodeStruct::ping();
|
||||
*node_clone.lock().unwrap() = result.nodes;
|
||||
*pinging_clone.lock().unwrap() = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Middle panel, contents of the [Tab]
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
// This sets the Ui dimensions after Top/Bottom are filled
|
||||
|
@ -655,7 +672,7 @@ impl eframe::App for App {
|
|||
Gupax::show(&mut self.state.gupax, &self.og, &self.state.version, &self.update, self.width, self.height, ctx, ui);
|
||||
}
|
||||
Tab::P2pool => {
|
||||
P2pool::show(&mut self.state.p2pool, self.width, self.height, ctx, ui);
|
||||
P2pool::show(&mut self.state.p2pool, &self.og, self.p2pool, &self.ping, &self.addr_regex, self.width, self.height, ctx, ui);
|
||||
}
|
||||
Tab::Xmrig => {
|
||||
Xmrig::show(&mut self.state.xmrig, self.width, self.height, ctx, ui);
|
||||
|
|
430
src/node.rs
430
src/node.rs
|
@ -20,10 +20,13 @@ use std::time::{Instant,Duration};
|
|||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::thread;
|
||||
use std::sync::{Arc,Mutex};
|
||||
use egui::Color32;
|
||||
use rand::Rng;
|
||||
use log::*;
|
||||
use reqwest::blocking::ClientBuilder;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Node list
|
||||
// Community Monerod nodes. All of these have ZMQ on 18083.
|
||||
// Adding/removing nodes will need changes to pretty
|
||||
// much all the code in this file, and the code that
|
||||
|
@ -33,37 +36,27 @@ pub const CAKE: &'static str = "xmr-node.cakewallet.com:18081";
|
|||
pub const CAKE_EU: &'static str = "xmr-node-eu.cakewallet.com:18081";
|
||||
pub const CAKE_UK: &'static str = "xmr-node-uk.cakewallet.com:18081";
|
||||
pub const CAKE_US: &'static str = "xmr-node-usa-east.cakewallet.com:18081";
|
||||
pub const MAJESTICBANK_IS: &'static str = "node.majesticbank.is:18089";
|
||||
pub const MAJESTICBANK_SU: &'static str = "node.majesticbank.su:18089";
|
||||
pub const MONERUJO: &'static str = "nodex.monerujo.io:18081";
|
||||
pub const RINO: &'static str = "node.community.rino.io:18081";
|
||||
pub const SELSTA: &'static str = "selsta1.featherwallet.net:18081";
|
||||
pub const SELSTA_1: &'static str = "selsta1.featherwallet.net:18081";
|
||||
pub const SELSTA_2: &'static str = "selsta2.featherwallet.net:18081";
|
||||
pub const SETH: &'static str = "node.sethforprivacy.com:18089";
|
||||
pub const SUPPORTXMR: &'static str = "node.supportxmr.com:18081";
|
||||
pub const SUPPORTXMR_IR: &'static str = "node.supportxmr.ir:18081";
|
||||
pub const SINGAPORE: &'static str = "singapore.node.xmr.pm:18089";
|
||||
pub const XMRVSBEAST: &'static str = "p2pmd.xmrvsbeast.com:18081";
|
||||
|
||||
pub const NODE_IPS: [&'static str; 12] = [
|
||||
C3POOL,CAKE,CAKE_EU,CAKE_UK,CAKE_US,MONERUJO,RINO,
|
||||
SELSTA,SETH,SUPPORTXMR,SUPPORTXMR_IR,XMRVSBEAST,
|
||||
pub const NODE_IPS: [&'static str; 16] = [
|
||||
C3POOL,CAKE,CAKE_EU,CAKE_UK,CAKE_US,MAJESTICBANK_IS,MAJESTICBANK_SU,MONERUJO,
|
||||
RINO,SELSTA_1,SELSTA_2,SETH,SUPPORTXMR,SUPPORTXMR_IR,SINGAPORE,XMRVSBEAST,
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NodeStruct {
|
||||
c3pool: Data, cake: Data, cake_eu: Data, cake_uk: Data, cake_us: Data, monerujo: Data,
|
||||
rino: Data, selsta: Data, seth: Data, supportxmr: Data, supportxmr_ir: Data, xmrvsbeast: Data,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Data {
|
||||
pub ms: u128,
|
||||
pub color: Color32,
|
||||
pub id: NodeEnum,
|
||||
pub ip: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Copy,Clone,Eq,PartialEq,Debug,Deserialize,Serialize)]
|
||||
pub enum NodeEnum {
|
||||
C3pool, Cake, CakeEu, CakeUk, CakeUs, Monerujo, Rino,
|
||||
Selsta, Seth, SupportXmr, SupportXmrIr, XmrVsBeast,
|
||||
C3pool,Cake,CakeEu,CakeUk,CakeUs,MajesticBankIs,MajesticBankSu,Monerujo,
|
||||
Rino,Selsta1,Selsta2,Seth,SupportXmr,SupportXmrIr,Singapore,XmrVsBeast,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for NodeEnum {
|
||||
|
@ -72,152 +65,265 @@ impl std::fmt::Display for NodeEnum {
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Node data
|
||||
#[derive(Debug)]
|
||||
pub struct NodeData {
|
||||
pub id: NodeEnum,
|
||||
pub ip: &'static str,
|
||||
pub ms: u128,
|
||||
pub color: Color32,
|
||||
}
|
||||
|
||||
impl NodeData {
|
||||
pub fn new_vec() -> Vec<Self> {
|
||||
let mut vec = Vec::new();
|
||||
for ip in NODE_IPS.iter() {
|
||||
vec.push(Self {
|
||||
id: ip_to_enum(ip),
|
||||
ip,
|
||||
ms: 0,
|
||||
color: Color32::LIGHT_GRAY,
|
||||
});
|
||||
}
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Ping data
|
||||
#[derive(Debug)]
|
||||
pub struct Ping {
|
||||
pub nodes: Vec<NodeData>,
|
||||
pub fastest: NodeEnum,
|
||||
pub pinging: bool,
|
||||
pub msg: String,
|
||||
pub prog: f32,
|
||||
pub pinged: bool,
|
||||
}
|
||||
|
||||
impl Ping {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
nodes: NodeData::new_vec(),
|
||||
fastest: NodeEnum::C3pool,
|
||||
pinging: false,
|
||||
msg: "No ping in progress".to_string(),
|
||||
prog: 0.0,
|
||||
pinged: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PingResult {
|
||||
pub nodes: NodeStruct,
|
||||
pub nodes: Vec<NodeData>,
|
||||
pub fastest: NodeEnum,
|
||||
}
|
||||
|
||||
use crate::NodeEnum::*;
|
||||
impl NodeStruct {
|
||||
pub fn default() -> Self {
|
||||
let ms = 0;
|
||||
let color = Color32::GRAY;
|
||||
Self {
|
||||
c3pool: Data { ms, color, id: C3pool, ip: C3POOL, },
|
||||
cake: Data { ms, color, id: Cake, ip: CAKE, },
|
||||
cake_eu: Data { ms, color, id: CakeEu, ip: CAKE_EU, },
|
||||
cake_uk: Data { ms, color, id: CakeUk, ip: CAKE_UK, },
|
||||
cake_us: Data { ms, color, id: CakeUs, ip: CAKE_US, },
|
||||
monerujo: Data { ms, color, id: Monerujo, ip: MONERUJO, },
|
||||
rino: Data { ms, color, id: Rino, ip: RINO, },
|
||||
selsta: Data { ms, color, id: Selsta, ip: SELSTA, },
|
||||
seth: Data { ms, color, id: Seth, ip: SETH, },
|
||||
supportxmr: Data { ms, color, id: SupportXmr, ip: SUPPORTXMR, },
|
||||
supportxmr_ir: Data { ms, color, id: SupportXmrIr, ip: SUPPORTXMR_IR, },
|
||||
xmrvsbeast: Data { ms, color, id: XmrVsBeast, ip: XMRVSBEAST, },
|
||||
}
|
||||
}
|
||||
|
||||
// This is for pinging the community nodes to
|
||||
// find the fastest/slowest one for the user.
|
||||
// The process:
|
||||
// - Send [get_info] JSON-RPC requests over HTTP
|
||||
// - To prevent fingerprinting, randomly send [2-4] calls
|
||||
// - Measure each request in milliseconds as [u128]
|
||||
// - Timeout on requests over 5 seconds
|
||||
// - Calculate average time
|
||||
// - Add data to appropriate struct
|
||||
// - Sort fastest to lowest
|
||||
// - Return [PingResult(NodeStruct, NodeEnum)] (data and fastest node)
|
||||
//
|
||||
// This is done linearly since per IP since
|
||||
// multi-threading might affect performance.
|
||||
//
|
||||
// <300ms = GREEN
|
||||
// <1000ms = YELLOW
|
||||
// >1000ms = RED
|
||||
// timeout = BLACK
|
||||
// default = GRAY
|
||||
pub fn ping() -> PingResult {
|
||||
info!("Starting community node pings...");
|
||||
// Get node list
|
||||
let mut nodes = NodeStruct::default();
|
||||
|
||||
// Create JSON request
|
||||
let mut get_info = HashMap::new();
|
||||
get_info.insert("jsonrpc", "2.0");
|
||||
get_info.insert("id", "0");
|
||||
get_info.insert("method", "get_info");
|
||||
|
||||
// Misc Settings
|
||||
let mut vec: Vec<(u128, NodeEnum)> = Vec::new();
|
||||
|
||||
// Create HTTP Client
|
||||
let timeout_sec = Duration::from_millis(5000);
|
||||
let client = reqwest::blocking::ClientBuilder::new();
|
||||
let client = reqwest::blocking::ClientBuilder::timeout(client, timeout_sec);
|
||||
let client = reqwest::blocking::ClientBuilder::build(client).unwrap();
|
||||
|
||||
for ip in NODE_IPS.iter() {
|
||||
// Match IP
|
||||
let id = match *ip {
|
||||
C3POOL => C3pool,
|
||||
CAKE => Cake,
|
||||
CAKE_EU => CakeEu,
|
||||
CAKE_UK => CakeUk,
|
||||
CAKE_US => CakeUs,
|
||||
MONERUJO => Monerujo,
|
||||
RINO => Rino,
|
||||
SELSTA => Selsta,
|
||||
SETH => Seth,
|
||||
SUPPORTXMR => SupportXmr,
|
||||
SUPPORTXMR_IR => SupportXmrIr,
|
||||
_ => XmrVsBeast,
|
||||
};
|
||||
// Misc
|
||||
let mut timeout = false;
|
||||
let mut mid = Duration::new(0, 0);
|
||||
let max = rand::thread_rng().gen_range(2..4);
|
||||
|
||||
// Start JSON-RPC request
|
||||
for i in 1..=max {
|
||||
let now = Instant::now();
|
||||
let http = "http://".to_owned() + &**ip + "/json_rpc";
|
||||
match client.post(http).json(&get_info).send() {
|
||||
Ok(_) => mid += now.elapsed(),
|
||||
Err(err) => {
|
||||
error!("Timeout on [{:#?}: {}] (over 5 seconds) | {}", id, ip, err);
|
||||
mid += timeout_sec;
|
||||
timeout = true;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Calculate average
|
||||
let ms = mid.as_millis() / 3;
|
||||
vec.push((ms, id));
|
||||
info!("{}ms ... {} calls ... {}", ms, max, ip);
|
||||
let color: Color32;
|
||||
if timeout == true {
|
||||
color = Color32::BLACK
|
||||
} else if ms >= 1000 {
|
||||
color = Color32::LIGHT_RED
|
||||
} else if ms >= 300 {
|
||||
color = Color32::LIGHT_YELLOW
|
||||
} else {
|
||||
color = Color32::LIGHT_GREEN
|
||||
}
|
||||
match id {
|
||||
C3pool => { nodes.c3pool.ms = ms; nodes.c3pool.color = color; },
|
||||
Cake => { nodes.cake.ms = ms; nodes.cake.color = color; },
|
||||
CakeEu => { nodes.cake_eu.ms = ms; nodes.cake_eu.color = color; },
|
||||
CakeUk => { nodes.cake_uk.ms = ms; nodes.cake_uk.color = color; },
|
||||
CakeUs => { nodes.cake_us.ms = ms; nodes.cake_us.color = color; },
|
||||
Monerujo => { nodes.monerujo.ms = ms; nodes.monerujo.color = color; },
|
||||
Rino => { nodes.rino.ms = ms; nodes.rino.color = color; },
|
||||
Selsta => { nodes.selsta.ms = ms; nodes.selsta.color = color; },
|
||||
Seth => { nodes.seth.ms = ms; nodes.seth.color = color; },
|
||||
SupportXmr => { nodes.supportxmr.ms = ms; nodes.supportxmr.color = color; },
|
||||
SupportXmrIr => { nodes.supportxmr_ir.ms = ms; nodes.supportxmr_ir.color = color; },
|
||||
XmrVsBeast => { nodes.xmrvsbeast.ms = ms; nodes.xmrvsbeast.color = color; },
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate fastest out of all nodes
|
||||
let mut best_ms: u128 = vec[0].0;
|
||||
let mut fastest: NodeEnum = vec[0].1;
|
||||
for (ms, id) in vec.iter() {
|
||||
if ms < &best_ms {
|
||||
fastest = *id;
|
||||
best_ms = *ms;
|
||||
}
|
||||
}
|
||||
// These values have weird behavior.
|
||||
// The values don't update if not printed beforehand,
|
||||
// so the match below on [fastest] gets funky.
|
||||
info!("Fastest node ... {:#?} @ {:#?}ms", fastest, best_ms);
|
||||
info!("Community node ping ... OK");
|
||||
PingResult { nodes, fastest, }
|
||||
//---------------------------------------------------------------------------------------------------- IP <-> Enum functions
|
||||
// Function for returning IP/Enum
|
||||
pub fn ip_to_enum(ip: &'static str) -> NodeEnum {
|
||||
match ip {
|
||||
C3POOL => C3pool,
|
||||
CAKE => Cake,
|
||||
CAKE_EU => CakeEu,
|
||||
CAKE_UK => CakeUk,
|
||||
CAKE_US => CakeUs,
|
||||
MAJESTICBANK_IS => MajesticBankIs,
|
||||
MAJESTICBANK_SU => MajesticBankSu,
|
||||
MONERUJO => Monerujo,
|
||||
RINO => Rino,
|
||||
SELSTA_1 => Selsta1,
|
||||
SELSTA_2 => Selsta2,
|
||||
SETH => Seth,
|
||||
SINGAPORE => Singapore,
|
||||
SUPPORTXMR => SupportXmr,
|
||||
SUPPORTXMR_IR => SupportXmrIr,
|
||||
_ => XmrVsBeast,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enum_to_ip(node: NodeEnum) -> &'static str {
|
||||
match node {
|
||||
C3pool => C3POOL,
|
||||
Cake => CAKE,
|
||||
CakeEu => CAKE_EU,
|
||||
CakeUk => CAKE_UK,
|
||||
CakeUs => CAKE_US,
|
||||
MajesticBankIs => MAJESTICBANK_IS,
|
||||
MajesticBankSu => MAJESTICBANK_SU,
|
||||
Monerujo => MONERUJO,
|
||||
Rino => RINO,
|
||||
Selsta1 => SELSTA_1,
|
||||
Selsta2 => SELSTA_2,
|
||||
Seth => SETH,
|
||||
Singapore => SINGAPORE,
|
||||
SupportXmr => SUPPORTXMR,
|
||||
SupportXmrIr => SUPPORTXMR_IR,
|
||||
_ => XMRVSBEAST
|
||||
}
|
||||
}
|
||||
|
||||
// 5000 = 4 max length
|
||||
pub fn format_ms(ms: u128) -> String {
|
||||
match ms.to_string().len() {
|
||||
1 => format!("{}ms ", ms),
|
||||
2 => format!("{}ms ", ms),
|
||||
3 => format!("{}ms ", ms),
|
||||
_ => format!("{}ms", ms),
|
||||
}
|
||||
}
|
||||
|
||||
// MajesticBankIs = 14 max length
|
||||
pub fn format_enum(id: NodeEnum) -> String {
|
||||
match id.to_string().len() {
|
||||
1 => format!("{} ", id),
|
||||
2 => format!("{} ", id),
|
||||
3 => format!("{} ", id),
|
||||
4 => format!("{} ", id),
|
||||
5 => format!("{} ", id),
|
||||
6 => format!("{} ", id),
|
||||
7 => format!("{} ", id),
|
||||
8 => format!("{} ", id),
|
||||
9 => format!("{} ", id),
|
||||
10 => format!("{} ", id),
|
||||
11 => format!("{} ", id),
|
||||
12 => format!("{} ", id),
|
||||
13 => format!("{} ", id),
|
||||
_ => format!("{}", id),
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Main Ping function
|
||||
// This is for pinging the community nodes to
|
||||
// find the fastest/slowest one for the user.
|
||||
// The process:
|
||||
// - Send 3 [get_info] JSON-RPC requests over HTTP
|
||||
// - Measure each request in milliseconds as [u128]
|
||||
// - Timeout on requests over 5 seconds
|
||||
// - Calculate average time
|
||||
// - Add data to appropriate struct
|
||||
// - Sort fastest to lowest
|
||||
// - Return [PingResult] (data and fastest node)
|
||||
//
|
||||
// This is done linearly since per IP since
|
||||
// multi-threading might affect performance.
|
||||
//
|
||||
// <300ms = GREEN
|
||||
// <1000ms = YELLOW
|
||||
// >1000ms = RED
|
||||
// timeout = BLACK
|
||||
// default = GRAY
|
||||
use crate::NodeEnum::*;
|
||||
pub fn ping(ping: Arc<Mutex<Ping>>) -> PingResult {
|
||||
// Start ping
|
||||
ping.lock().unwrap().pinging = true;
|
||||
ping.lock().unwrap().prog = 0.0;
|
||||
let info = format!("{}", "Creating HTTPS Client");
|
||||
info!("Ping | {}", info);
|
||||
ping.lock().unwrap().msg = info;
|
||||
let percent = (100 / (NODE_IPS.len() - 1)) as f32 / 3.0;
|
||||
|
||||
// Create Node vector
|
||||
let mut nodes = Vec::new();
|
||||
|
||||
// Create JSON request
|
||||
let mut get_info = HashMap::new();
|
||||
get_info.insert("jsonrpc", "2.0");
|
||||
get_info.insert("id", "0");
|
||||
get_info.insert("method", "get_info");
|
||||
|
||||
// Misc Settings
|
||||
let mut vec: Vec<(NodeEnum, u128)> = Vec::new();
|
||||
|
||||
// Create HTTP Client
|
||||
let timeout_sec = Duration::from_millis(5000);
|
||||
let client = ClientBuilder::new();
|
||||
let client = ClientBuilder::timeout(client, timeout_sec);
|
||||
let client = ClientBuilder::build(client).unwrap();
|
||||
|
||||
for ip in NODE_IPS.iter() {
|
||||
// Match IP
|
||||
let id = match *ip {
|
||||
C3POOL => C3pool,
|
||||
CAKE => Cake,
|
||||
CAKE_EU => CakeEu,
|
||||
CAKE_UK => CakeUk,
|
||||
CAKE_US => CakeUs,
|
||||
MAJESTICBANK_IS => MajesticBankIs,
|
||||
MAJESTICBANK_SU => MajesticBankSu,
|
||||
MONERUJO => Monerujo,
|
||||
RINO => Rino,
|
||||
SELSTA_1 => Selsta1,
|
||||
SELSTA_2 => Selsta2,
|
||||
SETH => Seth,
|
||||
SINGAPORE => Singapore,
|
||||
SUPPORTXMR => SupportXmr,
|
||||
SUPPORTXMR_IR => SupportXmrIr,
|
||||
_ => XmrVsBeast,
|
||||
};
|
||||
// Misc
|
||||
let mut timeout = 0;
|
||||
let mut mid = Duration::new(0, 0);
|
||||
|
||||
// Start JSON-RPC request
|
||||
for i in 1..=3 {
|
||||
ping.lock().unwrap().msg = format!("{}: {} [{}/3]", id, ip, i);
|
||||
let now = Instant::now();
|
||||
let http = "http://".to_string() + &**ip + "/json_rpc";
|
||||
match client.post(http).json(&get_info).send() {
|
||||
Ok(_) => mid += now.elapsed(),
|
||||
Err(err) => {
|
||||
mid += timeout_sec;
|
||||
timeout += 1;
|
||||
let error = format!("Timeout [{}/3] ... {:#?} ... {}", timeout, id, ip);
|
||||
error!("Ping | {}", error);
|
||||
ping.lock().unwrap().msg = error;
|
||||
},
|
||||
};
|
||||
ping.lock().unwrap().prog += percent;
|
||||
}
|
||||
|
||||
// Calculate average
|
||||
let ms = mid.as_millis() / 3;
|
||||
vec.push((id, ms));
|
||||
let info = format!("{}ms ... {}: {}", ms, id, ip);
|
||||
info!("Ping | {}", info);
|
||||
ping.lock().unwrap().msg = format!("{}", info);
|
||||
let color: Color32;
|
||||
if timeout == 3 {
|
||||
color = Color32::BLACK;
|
||||
} else if ms >= 1000 {
|
||||
// RED
|
||||
color = Color32::from_rgb(230, 50, 50);
|
||||
} else if ms >= 300 {
|
||||
// YELLOW
|
||||
color = Color32::from_rgb(230, 230, 100);
|
||||
} else {
|
||||
// GREEN
|
||||
color = Color32::from_rgb(100, 230, 100);
|
||||
}
|
||||
nodes.push(NodeData { id, ip, ms, color })
|
||||
}
|
||||
|
||||
let percent = (100.0 - ping.lock().unwrap().prog) / 2.0;
|
||||
ping.lock().unwrap().prog += percent;
|
||||
ping.lock().unwrap().msg = "Calculating fastest node".to_string();
|
||||
// Calculate fastest out of all nodes
|
||||
let mut fastest: NodeEnum = vec[0].0;
|
||||
let mut best_ms: u128 = vec[0].1;
|
||||
for (id, ms) in vec.iter() {
|
||||
if ms < &best_ms {
|
||||
fastest = *id;
|
||||
best_ms = *ms;
|
||||
}
|
||||
}
|
||||
let info = format!("Fastest node: {}ms ... {} @ {}", best_ms, fastest, enum_to_ip(fastest));
|
||||
let percent = (100.0 - ping.lock().unwrap().prog) / 2.0;
|
||||
info!("Ping | {}", info);
|
||||
ping.lock().unwrap().prog = 100.0;
|
||||
ping.lock().unwrap().msg = info;
|
||||
ping.lock().unwrap().pinging = false;
|
||||
ping.lock().unwrap().pinged = true;
|
||||
info!("Ping ... OK");
|
||||
PingResult { nodes, fastest }
|
||||
}
|
||||
|
|
181
src/p2pool.rs
181
src/p2pool.rs
|
@ -17,26 +17,163 @@
|
|||
|
||||
use crate::App;
|
||||
use crate::constants::*;
|
||||
use crate::state::P2pool;
|
||||
use crate::node::NodeEnum;
|
||||
use crate::node::{RINO,SETH,SELSTA};
|
||||
|
||||
// pub simple: bool,
|
||||
// pub mini: bool,
|
||||
// pub out_peers: u8,
|
||||
// pub in_peers: u8,
|
||||
// pub log_level: u8,
|
||||
// pub node: crate::node::NodeEnum,
|
||||
// pub monerod: String,
|
||||
// pub rpc: u16,
|
||||
// pub zmq: u16,
|
||||
// pub address: String,
|
||||
|
||||
use crate::state::*;
|
||||
use crate::node::*;
|
||||
use crate::node::NodeEnum::*;
|
||||
use std::sync::{Arc,Mutex};
|
||||
use std::thread;
|
||||
use log::*;
|
||||
use egui::{TextEdit,SelectableLabel,ComboBox,Label};
|
||||
use egui::TextStyle::*;
|
||||
use egui::FontFamily::Proportional;
|
||||
use egui::{FontId,Button,Color32,RichText};
|
||||
use regex::Regex;
|
||||
|
||||
impl P2pool {
|
||||
pub fn show(&mut self, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
pub fn show(&mut self, og: &Arc<Mutex<State>>, online: bool, ping: &Arc<Mutex<Ping>>, addr_regex: &Regex, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
let text_edit = height / 20.0;
|
||||
// Console
|
||||
ui.group(|ui| {
|
||||
let height = height / SPACE;
|
||||
let width = width - SPACE;
|
||||
ui.add_sized([width, height*3.0], TextEdit::multiline(&mut "".to_string()));
|
||||
ui.add_sized([width, text_edit], TextEdit::hint_text(TextEdit::singleline(&mut "".to_string()), r#"Type a command (e.g "help" or "status") and press Enter"#));
|
||||
});
|
||||
|
||||
let height = ui.available_height();
|
||||
// [Simple]
|
||||
if self.simple {
|
||||
// [Node]
|
||||
let height = height / 6.0;
|
||||
ui.spacing_mut().slider_width = width - 8.0;
|
||||
ui.spacing_mut().icon_width = width / 25.0;
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
// [Ping List]
|
||||
let id = og.lock().unwrap().p2pool.node;
|
||||
let ip = enum_to_ip(id);
|
||||
let mut ms = 0;
|
||||
let mut color = Color32::LIGHT_GRAY;
|
||||
for data in ping.lock().unwrap().nodes.iter() {
|
||||
if data.id == id {
|
||||
ms = data.ms;
|
||||
color = data.color;
|
||||
break
|
||||
}
|
||||
}
|
||||
let text = RichText::new(format!("⏺ {}ms | {} | {}", ms, id, ip)).color(color);
|
||||
ComboBox::from_id_source("nodes").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
|
||||
for data in ping.lock().unwrap().nodes.iter() {
|
||||
let ms = crate::node::format_ms(data.ms);
|
||||
let id = crate::node::format_enum(data.id);
|
||||
let text = RichText::text_style(RichText::new(format!("⏺ {} | {} | {}", ms, id, data.ip)).color(data.color), Monospace);
|
||||
ui.selectable_value(&mut og.lock().unwrap().p2pool.node, data.id, text);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(5.0);
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
let width = (width/2.0)-4.0;
|
||||
// [Select fastest node]
|
||||
if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() {
|
||||
let pinged = ping.lock().unwrap().pinged;
|
||||
let fastest = ping.lock().unwrap().fastest;
|
||||
if pinged && og.lock().unwrap().p2pool.node != fastest {
|
||||
og.lock().unwrap().p2pool.node = ping.lock().unwrap().fastest;
|
||||
og.lock().unwrap().save();
|
||||
}
|
||||
}
|
||||
// [Ping Button]
|
||||
ui.set_enabled(!ping.lock().unwrap().pinging);
|
||||
if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() {
|
||||
let ping = Arc::clone(&ping);
|
||||
let og_clone = Arc::clone(og);
|
||||
ping.lock().unwrap().pinging = true;
|
||||
thread::spawn(move|| {
|
||||
info!("Spawning ping thread...");
|
||||
let ping_result = crate::node::ping(ping.clone());
|
||||
ping.lock().unwrap().nodes = ping_result.nodes;
|
||||
ping.lock().unwrap().fastest = ping_result.fastest;
|
||||
if og_clone.lock().unwrap().p2pool.auto_select {
|
||||
og_clone.lock().unwrap().p2pool.node = ping_result.fastest;
|
||||
og_clone.lock().unwrap().save();
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
ui.vertical(|ui| {
|
||||
let height = height / 2.0;
|
||||
let pinging = ping.lock().unwrap().pinging;
|
||||
ui.set_enabled(pinging);
|
||||
let prog = ping.lock().unwrap().prog.round();
|
||||
let msg = RichText::text_style(RichText::new(format!("{} ... {}%", ping.lock().unwrap().msg, prog)), Monospace);
|
||||
let height = height / 1.25;
|
||||
ui.add_space(5.0);
|
||||
ui.add_sized([width, height], Label::new(msg));
|
||||
ui.add_space(5.0);
|
||||
if pinging {
|
||||
ui.add_sized([width, height], egui::Spinner::new().size(height));
|
||||
} else {
|
||||
ui.add_sized([width, height], egui::Label::new("..."));
|
||||
}
|
||||
ui.add_sized([width, height], egui::ProgressBar::new(prog.round()/100.0));
|
||||
ui.add_space(5.0);
|
||||
});
|
||||
});
|
||||
|
||||
ui.group(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
let width = (width/2.0)-(SPACE*1.5);
|
||||
// [Auto-node] + [Auto-select]
|
||||
let mut style = (*ctx.style()).clone();
|
||||
style.spacing.icon_width_inner = height/1.5;
|
||||
style.spacing.icon_width = height;
|
||||
style.spacing.icon_spacing = 20.0;
|
||||
ctx.set_style(style);
|
||||
ui.add_sized([width, height], egui::Checkbox::new(&mut self.auto_select, "Auto-select")).on_hover_text(P2POOL_AUTO_SELECT);
|
||||
ui.separator();
|
||||
ui.add_sized([width, height], egui::Checkbox::new(&mut self.auto_node, "Auto-node")).on_hover_text(P2POOL_AUTO_NODE);
|
||||
})});
|
||||
|
||||
// [Address]
|
||||
let height = ui.available_height();
|
||||
ui.horizontal(|ui| {
|
||||
let width = width / 100.0;
|
||||
ui.add_sized([width*6.0, height], Label::new("Address"));
|
||||
if self.address.is_empty() {
|
||||
ui.add_sized([width, height], Label::new(RichText::new("➖").color(Color32::LIGHT_GRAY)));
|
||||
} else if self.address.len() == 95 && Regex::is_match(addr_regex, &self.address) {
|
||||
ui.add_sized([width, height], Label::new(RichText::new("✔").color(Color32::from_rgb(100, 230, 100))));
|
||||
} else {
|
||||
ui.add_sized([width, height], Label::new(RichText::new("❌").color(Color32::from_rgb(230, 50, 50))));
|
||||
}
|
||||
ui.spacing_mut().text_edit_width = (width*9.0)-(SPACE*2.5);
|
||||
ui.style_mut().override_text_style = Some(Monospace);
|
||||
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.address), "4...")).on_hover_text(P2POOL_ADDRESS);
|
||||
});
|
||||
// ui.horizontal(|ui| {
|
||||
// ui.add_sized([width, height/2.0], Label::new("Address:"));
|
||||
// ui.add_sized([width, height], TextEdit::multiline(&mut self.address));
|
||||
// })});
|
||||
// [Advanced]
|
||||
} else {
|
||||
// TODO:
|
||||
// ping code
|
||||
// If ping was pressed, start thread
|
||||
// if self.ping {
|
||||
// self.ping = false;
|
||||
// self.pinging = Arc::new(Mutex::new(true));
|
||||
// let node_clone = Arc::clone(&self.node);
|
||||
// let pinging_clone = Arc::clone(&self.pinging);
|
||||
// thread::spawn(move|| {
|
||||
// let result = NodeStruct::ping();
|
||||
// *node_clone.lock().unwrap() = result.nodes;
|
||||
// *pinging_clone.lock().unwrap() = false;
|
||||
// });
|
||||
// }
|
||||
|
||||
// If ping-ING, display stats
|
||||
// if *self.pinging.lock().unwrap() {
|
||||
// egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
@ -58,14 +195,7 @@ impl P2pool {
|
|||
// return
|
||||
// }
|
||||
|
||||
let height = ui.available_height() / 10.0;
|
||||
let mut width = ui.available_width() - 50.0;
|
||||
ui.group(|ui| {
|
||||
ui.add_sized([width, height*4.0], egui::TextEdit::multiline(&mut "".to_owned()));
|
||||
ui.add_sized([width, 30.0], egui::TextEdit::singleline(&mut "".to_owned()));
|
||||
});
|
||||
|
||||
width = width - 30.0;
|
||||
let width = width - 30.0;
|
||||
let mut style = (*ctx.style()).clone();
|
||||
let height = ui.available_height()/1.2;
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -105,7 +235,7 @@ impl P2pool {
|
|||
egui::ComboBox::from_label(self.node.to_string()).selected_text(RINO).show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut self.node, NodeEnum::Rino, RINO);
|
||||
ui.selectable_value(&mut self.node, NodeEnum::Seth, SETH);
|
||||
ui.selectable_value(&mut self.node, NodeEnum::Selsta, SELSTA);
|
||||
ui.selectable_value(&mut self.node, NodeEnum::Selsta1, SELSTA_1);
|
||||
});
|
||||
// );
|
||||
});
|
||||
|
@ -138,4 +268,5 @@ impl P2pool {
|
|||
ui.text_edit_singleline(&mut self.address);
|
||||
})});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ impl State {
|
|||
p2pool: P2pool {
|
||||
simple: true,
|
||||
mini: true,
|
||||
auto_node: true,
|
||||
auto_select: true,
|
||||
out_peers: 10,
|
||||
in_peers: 10,
|
||||
log_level: 3,
|
||||
|
@ -311,6 +313,8 @@ pub struct Gupax {
|
|||
pub struct P2pool {
|
||||
pub simple: bool,
|
||||
pub mini: bool,
|
||||
pub auto_node: bool,
|
||||
pub auto_select: bool,
|
||||
pub out_peers: u16,
|
||||
pub in_peers: u16,
|
||||
pub log_level: u8,
|
||||
|
|
Loading…
Reference in a new issue