Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c48fa6b8c | |||
| 689cb3a9c2 | |||
| 60870fc458 | |||
| b44997f412 | |||
| 34aaa60a44 | |||
| dfa4563d22 | |||
| f30cc7a8a1 | |||
| 4f08161315 | |||
| 23d4c75597 | |||
| c24ca29212 | |||
| 6cff49caf6 | |||
| ea31aa6bcf | |||
| 410683dae6 | |||
| 043fb31c09 | |||
| e36573463c | |||
| c79471e9ad | |||
| 1cd8713d26 | |||
| edb797da68 | |||
| 72e1290d8f | |||
| 905d8ed7de | |||
| 4e5ccf7926 | |||
| 0a8eb940bb | |||
| 34fb67602c | |||
| 766ae8dd8e | |||
| bd1fd73ba0 |
Generated
+127
-89
@@ -11,7 +11,7 @@ dependencies = [
|
||||
"macroific",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -408,7 +408,7 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -490,7 +490,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -501,7 +501,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -709,7 +709,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1323,7 +1323,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1345,7 +1345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1563,7 +1563,7 @@ checksum = "a782b93fae93e57ca8ad3e9e994e784583f5933aeaaa5c80a545c4b437be2047"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1587,7 +1587,7 @@ checksum = "e01c9214319017f6ebd8e299036e1f717fa9bb6724e758f7d6fb2477599d1a29"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1831,7 +1831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1929,7 +1929,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2081,7 +2081,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2092,7 +2092,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2145,7 +2145,7 @@ dependencies = [
|
||||
"macroific",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2188,7 +2188,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2217,7 +2217,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
@@ -2229,7 +2229,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
@@ -2298,7 +2298,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2357,7 +2357,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2507,7 +2507,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2637,7 +2637,7 @@ dependencies = [
|
||||
"macroific",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2867,7 +2867,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3720,7 +3720,7 @@ checksum = "0ab604ee7085efba6efc65e4ebca0e9533e3aff6cb501d7d77b211e3a781c6d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3789,7 +3789,7 @@ dependencies = [
|
||||
"macroific",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3891,9 +3891,9 @@ checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02"
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.20"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83"
|
||||
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
@@ -3960,7 +3960,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4039,7 +4039,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4285,7 +4285,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sealed",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4297,7 +4297,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sealed",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4310,7 +4310,7 @@ dependencies = [
|
||||
"macroific_core",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4338,7 +4338,7 @@ checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4831,6 +4831,7 @@ dependencies = [
|
||||
"nym-ecash-signer-check",
|
||||
"nym-ecash-time",
|
||||
"nym-gateway-client",
|
||||
"nym-http-api-client",
|
||||
"nym-http-api-common",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-node-requests",
|
||||
@@ -5042,6 +5043,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-ecash-contract-common",
|
||||
"nym-ecash-time",
|
||||
"nym-http-api-client",
|
||||
"nym-id",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-multisig-contract-common",
|
||||
@@ -5130,6 +5132,7 @@ dependencies = [
|
||||
"nym-http-api-client",
|
||||
"nym-id",
|
||||
"nym-mixnet-client",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-network-defaults",
|
||||
"nym-nonexhaustive-delayqueue",
|
||||
"nym-pemstore",
|
||||
@@ -5482,6 +5485,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-ecash-contract-common",
|
||||
"nym-ecash-time",
|
||||
"nym-http-api-client",
|
||||
"nym-network-defaults",
|
||||
"nym-serde-helpers",
|
||||
"nym-validator-client",
|
||||
@@ -5581,6 +5585,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"nym-ecash-signer-check-types",
|
||||
"nym-http-api-client",
|
||||
"nym-network-defaults",
|
||||
"nym-validator-client",
|
||||
"semver 1.0.26",
|
||||
@@ -5841,14 +5846,19 @@ dependencies = [
|
||||
"encoding_rs",
|
||||
"hickory-resolver",
|
||||
"http 1.3.1",
|
||||
"inventory",
|
||||
"itertools 0.14.0",
|
||||
"mime",
|
||||
"nym-bin-common",
|
||||
"nym-http-api-client-macro",
|
||||
"nym-http-api-common",
|
||||
"nym-network-defaults",
|
||||
"once_cell",
|
||||
"reqwest 0.12.22",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"serde_yaml",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -5856,6 +5866,18 @@ dependencies = [
|
||||
"wasmtimer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-http-api-client-macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nym-http-api-client",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"reqwest 0.12.22",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-http-api-common"
|
||||
version = "0.1.0"
|
||||
@@ -6105,6 +6127,8 @@ dependencies = [
|
||||
"nym-client-core",
|
||||
"nym-crypto",
|
||||
"nym-gateway-requests",
|
||||
"nym-http-api-client",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-network-defaults",
|
||||
"nym-sdk",
|
||||
"nym-sphinx",
|
||||
@@ -6572,6 +6596,7 @@ dependencies = [
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-gateway-requests",
|
||||
"nym-http-api-client",
|
||||
"nym-network-defaults",
|
||||
"nym-ordered-buffer",
|
||||
"nym-service-providers-common",
|
||||
@@ -7147,6 +7172,7 @@ dependencies = [
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-ecash-time",
|
||||
"nym-http-api-client",
|
||||
"nym-network-defaults",
|
||||
"nym-pemstore",
|
||||
"nym-serde-helpers",
|
||||
@@ -7176,7 +7202,9 @@ dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"humantime",
|
||||
"nym-api-requests",
|
||||
"nym-crypto",
|
||||
"nym-http-api-client",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"rand 0.8.5",
|
||||
@@ -7784,7 +7812,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7847,7 +7875,7 @@ dependencies = [
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7876,7 +7904,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8084,6 +8112,15 @@ dependencies = [
|
||||
"elliptic-curve",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
|
||||
dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
@@ -8137,7 +8174,7 @@ dependencies = [
|
||||
"itertools 0.14.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8252,7 +8289,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8402,7 +8439,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8651,7 +8688,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@@ -8736,7 +8773,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8955,7 +8992,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals 0.29.1",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8987,7 +9024,7 @@ checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9008,7 +9045,7 @@ checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9148,7 +9185,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9159,7 +9196,7 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9170,7 +9207,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9232,7 +9269,7 @@ checksum = "aafbefbe175fa9bf03ca83ef89beecff7d2a95aaacd5732325b90ac8c3bd7b90"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9245,6 +9282,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.20"
|
||||
@@ -9253,7 +9299,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9306,7 +9352,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9652,7 +9698,7 @@ dependencies = [
|
||||
"quote",
|
||||
"sqlx-core",
|
||||
"sqlx-macros-core",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9675,7 +9721,7 @@ dependencies = [
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
@@ -9884,7 +9930,7 @@ dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9927,9 +9973,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.104"
|
||||
version = "2.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -9959,7 +10005,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10030,7 +10076,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.8",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10167,6 +10213,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-ecash-contract-common",
|
||||
"nym-group-contract-common",
|
||||
"nym-http-api-client",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-multisig-contract-common",
|
||||
"nym-pemstore",
|
||||
@@ -10222,7 +10269,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10233,7 +10280,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10365,7 +10412,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10686,7 +10733,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10856,7 +10903,7 @@ checksum = "0e9d8656589772eeec2cf7a8264d9cda40fb28b9bc53118ceb9e8c07f8f38730"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
@@ -10883,7 +10930,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals 0.28.0",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11073,7 +11120,7 @@ dependencies = [
|
||||
"indexmap 2.10.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11088,7 +11135,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"toml 0.5.11",
|
||||
"uniffi_meta",
|
||||
]
|
||||
@@ -11215,7 +11262,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
@@ -11254,7 +11301,7 @@ checksum = "268d76aaebb80eba79240b805972e52d7d410d4bcc52321b951318b0f440cd60"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11265,7 +11312,7 @@ checksum = "382673bda1d05c85b4550d32fd4192ccd4cffe9a908543a0795d1e7682b36246"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"utoipauto-core",
|
||||
]
|
||||
|
||||
@@ -11289,6 +11336,7 @@ dependencies = [
|
||||
"clap",
|
||||
"comfy-table",
|
||||
"nym-bin-common",
|
||||
"nym-http-api-client",
|
||||
"nym-network-defaults",
|
||||
"nym-validator-client",
|
||||
"serde",
|
||||
@@ -11433,7 +11481,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -11468,7 +11516,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -11503,7 +11551,7 @@ checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11519,6 +11567,7 @@ dependencies = [
|
||||
"nym-credential-storage",
|
||||
"nym-crypto",
|
||||
"nym-gateway-client",
|
||||
"nym-http-api-client",
|
||||
"nym-sphinx",
|
||||
"nym-sphinx-acknowledgements",
|
||||
"nym-statistics-common",
|
||||
@@ -11711,7 +11760,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11774,7 +11823,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11785,7 +11834,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11804,17 +11853,6 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
@@ -12220,7 +12258,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -12241,7 +12279,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12261,7 +12299,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -12282,7 +12320,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -12315,7 +12353,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
"syn 2.0.106",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+3
-1
@@ -57,7 +57,7 @@ members = [
|
||||
"common/gateway-requests",
|
||||
"common/gateway-stats-storage",
|
||||
"common/gateway-storage",
|
||||
"common/http-api-client",
|
||||
"common/http-api-client", "common/http-api-client-macro",
|
||||
"common/http-api-common",
|
||||
"common/inclusion-probability",
|
||||
"common/ip-packet-requests",
|
||||
@@ -271,6 +271,7 @@ hyper = "1.6.0"
|
||||
hyper-util = "0.1"
|
||||
indicatif = "0.18.0"
|
||||
inquire = "0.6.2"
|
||||
inventory = "0.3.21"
|
||||
ip_network = "0.4.1"
|
||||
ipnetwork = "0.20"
|
||||
itertools = "0.14.0"
|
||||
@@ -317,6 +318,7 @@ serde_json_path = "0.7.2"
|
||||
serde_repr = "0.1"
|
||||
serde_with = "3.9.0"
|
||||
serde_yaml = "0.9.25"
|
||||
serde_plain = "1.0.2"
|
||||
sha2 = "0.10.9"
|
||||
si-scale = "0.2.3"
|
||||
snow = "0.9.6"
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::error::BandwidthControllerError;
|
||||
use crate::utils::{
|
||||
get_aggregate_verification_key, get_coin_index_signatures, get_expiration_date_signatures,
|
||||
};
|
||||
use log::info;
|
||||
use log::{error, info};
|
||||
use nym_credential_storage::storage::Storage;
|
||||
use nym_credentials::ecash::bandwidth::IssuanceTicketBook;
|
||||
use nym_credentials::ecash::utils::obtain_aggregate_wallet;
|
||||
@@ -42,7 +42,8 @@ where
|
||||
deposit_amount.into(),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
.await
|
||||
.inspect_err(|err| error!("ticketbook deposit fail with: {err}"))?;
|
||||
|
||||
let deposit_id = result.parse_singleton_u32_contract_data()?;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use nym_credentials_interface::{
|
||||
};
|
||||
use nym_ecash_time::Date;
|
||||
use nym_validator_client::coconut::all_ecash_api_clients;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nym_api::{EpochId, NymApiClientExt};
|
||||
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
|
||||
use nym_validator_client::EcashApiClient;
|
||||
use rand::prelude::SliceRandom;
|
||||
|
||||
@@ -53,6 +53,7 @@ nym-client-core-config-types = { path = "./config-types", features = [
|
||||
nym-client-core-surb-storage = { path = "./surb-storage" }
|
||||
nym-client-core-gateways-storage = { path = "./gateways-storage" }
|
||||
nym-ecash-time = { path = "../ecash-time" }
|
||||
nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" }
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
|
||||
nym-mixnet-client = { path = "../client-libs/mixnet-client", default-features = false }
|
||||
|
||||
@@ -57,7 +57,7 @@ use nym_task::{TaskClient, TaskHandle};
|
||||
use nym_topology::provider_trait::TopologyProvider;
|
||||
use nym_topology::HardcodedTopologyProvider;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, NymApiClient, UserAgent};
|
||||
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::thread_rng;
|
||||
@@ -566,7 +566,7 @@ where
|
||||
custom_provider: Option<Box<dyn TopologyProvider + Send + Sync>>,
|
||||
config_topology: config::Topology,
|
||||
nym_api_urls: Vec<Url>,
|
||||
nym_api_client: NymApiClient,
|
||||
nym_api_client: nym_http_api_client::Client,
|
||||
) -> Box<dyn TopologyProvider + Send + Sync> {
|
||||
// if no custom provider was ... provided ..., create one using nym-api
|
||||
custom_provider.unwrap_or_else(|| {
|
||||
@@ -749,21 +749,31 @@ where
|
||||
setup_gateway(setup_method, key_store, details_store).await
|
||||
}
|
||||
|
||||
fn construct_nym_api_client(config: &Config, user_agent: Option<UserAgent>) -> NymApiClient {
|
||||
fn construct_nym_api_client(
|
||||
config: &Config,
|
||||
user_agent: Option<UserAgent>,
|
||||
) -> Result<nym_http_api_client::Client, ClientCoreError> {
|
||||
let mut nym_api_urls = config.get_nym_api_endpoints();
|
||||
nym_api_urls.shuffle(&mut thread_rng());
|
||||
|
||||
let mut builder = nym_http_api_client::Client::builder(nym_api_urls[0].clone())
|
||||
.map_err(|source| ClientCoreError::NymApiQueryFailure { source })?;
|
||||
|
||||
if let Some(user_agent) = user_agent {
|
||||
NymApiClient::new_with_user_agent(nym_api_urls[0].clone(), user_agent)
|
||||
} else {
|
||||
NymApiClient::new(nym_api_urls[0].clone())
|
||||
builder = builder.with_user_agent(user_agent);
|
||||
}
|
||||
|
||||
builder = builder.with_bincode();
|
||||
|
||||
builder
|
||||
.build()
|
||||
.map_err(|source| ClientCoreError::NymApiQueryFailure { source })
|
||||
}
|
||||
|
||||
async fn determine_key_rotation_state(
|
||||
client: &NymApiClient,
|
||||
client: &nym_http_api_client::Client,
|
||||
) -> Result<KeyRotationConfig, ClientCoreError> {
|
||||
Ok(client.nym_api.get_key_rotation_info().await?.into())
|
||||
Ok(client.get_key_rotation_info().await?.into())
|
||||
}
|
||||
|
||||
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError>
|
||||
@@ -830,7 +840,7 @@ where
|
||||
.dkg_query_client
|
||||
.map(|client| BandwidthController::new(credential_store, client));
|
||||
|
||||
let nym_api_client = Self::construct_nym_api_client(&self.config, self.user_agent.clone());
|
||||
let nym_api_client = Self::construct_nym_api_client(&self.config, self.user_agent.clone())?;
|
||||
let key_rotation_config = Self::determine_key_rotation_state(&nym_api_client).await?;
|
||||
|
||||
let topology_provider = Self::setup_topology_provider(
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use async_trait::async_trait;
|
||||
use nym_mixnet_contract_common::EpochRewardedSet;
|
||||
use nym_topology::provider_trait::{ToTopologyMetadata, TopologyProvider};
|
||||
use nym_topology::NymTopology;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::cmp::min;
|
||||
@@ -39,30 +41,43 @@ impl Config {
|
||||
pub struct NymApiTopologyProvider {
|
||||
config: Config,
|
||||
|
||||
validator_client: nym_validator_client::client::NymApiClient,
|
||||
validator_client: nym_http_api_client::Client,
|
||||
nym_api_urls: Vec<Url>,
|
||||
currently_used_api: usize,
|
||||
use_bincode: bool,
|
||||
}
|
||||
|
||||
impl NymApiTopologyProvider {
|
||||
pub fn new(
|
||||
config: impl Into<Config>,
|
||||
mut nym_api_urls: Vec<Url>,
|
||||
mut validator_client: nym_validator_client::client::NymApiClient,
|
||||
validator_client: nym_http_api_client::Client,
|
||||
) -> Self {
|
||||
nym_api_urls.shuffle(&mut thread_rng());
|
||||
validator_client.change_nym_api(nym_api_urls[0].clone());
|
||||
|
||||
NymApiTopologyProvider {
|
||||
let mut provider = NymApiTopologyProvider {
|
||||
config: config.into(),
|
||||
validator_client,
|
||||
nym_api_urls,
|
||||
currently_used_api: 0,
|
||||
}
|
||||
use_bincode: true,
|
||||
};
|
||||
// Set all API URLs - the client will try them in order with automatic failover
|
||||
provider.validator_client.change_base_urls(
|
||||
provider
|
||||
.nym_api_urls
|
||||
.iter()
|
||||
.map(|u| u.clone().into())
|
||||
.collect(),
|
||||
);
|
||||
provider
|
||||
}
|
||||
|
||||
pub fn disable_bincode(&mut self) {
|
||||
self.validator_client.use_bincode = false;
|
||||
self.use_bincode = false;
|
||||
// Note: The unified client doesn't support toggling bincode after creation.
|
||||
// This would require recreating the client without bincode.
|
||||
// For now, we'll track the preference but it won't take effect.
|
||||
warn!("Disabling bincode on existing client is not currently supported");
|
||||
}
|
||||
|
||||
fn use_next_nym_api(&mut self) {
|
||||
@@ -72,8 +87,19 @@ impl NymApiTopologyProvider {
|
||||
}
|
||||
|
||||
self.currently_used_api = (self.currently_used_api + 1) % self.nym_api_urls.len();
|
||||
self.validator_client
|
||||
.change_nym_api(self.nym_api_urls[self.currently_used_api].clone())
|
||||
|
||||
// Provide all URLs starting from the next one in rotation order
|
||||
// This enables automatic failover to other endpoints
|
||||
let rotated_urls: Vec<_> = self
|
||||
.nym_api_urls
|
||||
.iter()
|
||||
.cycle()
|
||||
.skip(self.currently_used_api)
|
||||
.take(self.nym_api_urls.len())
|
||||
.map(|u| u.clone().into())
|
||||
.collect();
|
||||
|
||||
self.validator_client.change_base_urls(rotated_urls)
|
||||
}
|
||||
|
||||
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
|
||||
@@ -99,8 +125,13 @@ impl NymApiTopologyProvider {
|
||||
.filter(|n| n.performance.round_to_integer() >= self.config.min_node_performance())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
NymTopology::new(metadata.to_topology_metadata(), rewarded_set, Vec::new())
|
||||
.with_skimmed_nodes(&nodes_filtered)
|
||||
let epoch_rewarded_set: EpochRewardedSet = rewarded_set.into();
|
||||
NymTopology::new(
|
||||
metadata.to_topology_metadata(),
|
||||
epoch_rewarded_set,
|
||||
Vec::new(),
|
||||
)
|
||||
.with_skimmed_nodes(&nodes_filtered)
|
||||
} else {
|
||||
// if we're not using extended topology, we're only getting active set mixnodes and gateways
|
||||
|
||||
@@ -148,8 +179,13 @@ impl NymApiTopologyProvider {
|
||||
}
|
||||
}
|
||||
|
||||
NymTopology::new(metadata.to_topology_metadata(), rewarded_set, Vec::new())
|
||||
.with_skimmed_nodes(&nodes)
|
||||
let epoch_rewarded_set: EpochRewardedSet = rewarded_set.into();
|
||||
NymTopology::new(
|
||||
metadata.to_topology_metadata(),
|
||||
epoch_rewarded_set,
|
||||
Vec::new(),
|
||||
)
|
||||
.with_skimmed_nodes(&nodes)
|
||||
};
|
||||
|
||||
if !topology.is_minimally_routable() {
|
||||
|
||||
@@ -7,7 +7,8 @@ use futures::{SinkExt, StreamExt};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway_client::GatewayClient;
|
||||
use nym_topology::node::RoutingNode;
|
||||
use nym_validator_client::client::IdentityKeyRef;
|
||||
use nym_validator_client::client::{IdentityKeyRef, NymApiClientExt};
|
||||
use nym_validator_client::nym_nodes::SkimmedNodesWithMetadata;
|
||||
use nym_validator_client::UserAgent;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
#[cfg(unix)]
|
||||
@@ -83,6 +84,48 @@ struct GatewayWithLatency<'a, G: ConnectableGateway> {
|
||||
latency: Duration,
|
||||
}
|
||||
|
||||
// Helper to collect all pages of entry nodes - replicates NymApiClient's convenience method
|
||||
async fn get_all_basic_entry_nodes_with_metadata(
|
||||
client: &nym_http_api_client::Client,
|
||||
use_bincode: bool,
|
||||
) -> Result<SkimmedNodesWithMetadata, ClientCoreError> {
|
||||
// Get first page to obtain metadata
|
||||
let mut page = 0;
|
||||
let res = client
|
||||
.get_basic_entry_assigned_nodes_v2(false, Some(page), None, use_bincode)
|
||||
.await?;
|
||||
let mut nodes = res.nodes.data;
|
||||
let metadata = res.metadata;
|
||||
|
||||
if res.nodes.pagination.total == nodes.len() {
|
||||
return Ok(SkimmedNodesWithMetadata::new(nodes, metadata));
|
||||
}
|
||||
|
||||
page += 1;
|
||||
|
||||
// Collect remaining pages
|
||||
loop {
|
||||
let mut res = client
|
||||
.get_basic_entry_assigned_nodes_v2(false, Some(page), None, use_bincode)
|
||||
.await?;
|
||||
|
||||
if !metadata.consistency_check(&res.metadata) {
|
||||
return Err(ClientCoreError::ValidatorClientError(
|
||||
nym_validator_client::ValidatorClientError::InconsistentPagedMetadata,
|
||||
));
|
||||
}
|
||||
|
||||
nodes.append(&mut res.nodes.data);
|
||||
if nodes.len() < res.nodes.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SkimmedNodesWithMetadata::new(nodes, metadata))
|
||||
}
|
||||
|
||||
impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
|
||||
fn new(gateway: &'a G, latency: Duration) -> Self {
|
||||
GatewayWithLatency { gateway, latency }
|
||||
@@ -99,16 +142,30 @@ pub async fn gateways_for_init<R: Rng>(
|
||||
let nym_api = nym_apis
|
||||
.choose(rng)
|
||||
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
|
||||
let client = if let Some(user_agent) = user_agent {
|
||||
nym_validator_client::client::NymApiClient::new_with_user_agent(nym_api.clone(), user_agent)
|
||||
} else {
|
||||
nym_validator_client::client::NymApiClient::new(nym_api.clone())
|
||||
};
|
||||
|
||||
// Use the unified HTTP client directly with optional user agent
|
||||
let mut builder = nym_http_api_client::Client::builder(nym_api.clone())
|
||||
.map_err(|e| {
|
||||
ClientCoreError::ValidatorClientError(
|
||||
nym_validator_client::ValidatorClientError::NymAPIError { source: e },
|
||||
)
|
||||
})?
|
||||
.with_bincode(); // Use bincode for better performance
|
||||
|
||||
if let Some(user_agent) = user_agent {
|
||||
builder = builder.with_user_agent(user_agent);
|
||||
}
|
||||
|
||||
let client = builder.build().map_err(|e| {
|
||||
ClientCoreError::ValidatorClientError(
|
||||
nym_validator_client::ValidatorClientError::NymAPIError { source: e },
|
||||
)
|
||||
})?;
|
||||
|
||||
tracing::debug!("Fetching list of gateways from: {nym_api}");
|
||||
|
||||
let gateways = client
|
||||
.get_all_basic_entry_assigned_nodes_with_metadata()
|
||||
// Use our helper to handle pagination
|
||||
let gateways = get_all_basic_entry_nodes_with_metadata(&client, true)
|
||||
.await?
|
||||
.nodes;
|
||||
info!("nym api reports {} gateways", gateways.len());
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::nyxd::{self, NyxdClient};
|
||||
use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
||||
use crate::signing::signer::{NoSigner, OfflineSigner};
|
||||
use crate::{
|
||||
nym_api, DirectSigningReqwestRpcValidatorClient, QueryReqwestRpcValidatorClient,
|
||||
ReqwestRpcClient, ValidatorClientError,
|
||||
DirectSigningReqwestRpcValidatorClient, QueryReqwestRpcValidatorClient, ReqwestRpcClient,
|
||||
ValidatorClientError,
|
||||
};
|
||||
use nym_api_requests::ecash::models::{
|
||||
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
||||
@@ -153,7 +153,7 @@ impl Config {
|
||||
pub struct Client<C, S = NoSigner> {
|
||||
// ideally they would have been read-only, but unfortunately rust doesn't have such features
|
||||
// #[deprecated(note = "please use `nym_api_client` instead")]
|
||||
pub nym_api: nym_api::Client,
|
||||
pub nym_api: nym_http_api_client::Client,
|
||||
// pub nym_api_client: NymApiClient,
|
||||
pub nyxd: NyxdClient<C, S>,
|
||||
}
|
||||
@@ -214,7 +214,7 @@ impl Client<ReqwestRpcClient> {
|
||||
|
||||
impl<C> Client<C> {
|
||||
pub fn new_with_rpc_client(config: Config, rpc_client: C) -> Self {
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone(), None);
|
||||
let nym_api_client = nym_http_api_client::Client::new(config.api_url.clone(), None);
|
||||
|
||||
Client {
|
||||
nym_api: nym_api_client,
|
||||
@@ -228,7 +228,7 @@ impl<C, S> Client<C, S> {
|
||||
where
|
||||
S: OfflineSigner,
|
||||
{
|
||||
let nym_api_client = nym_api::Client::new(config.api_url.clone(), None);
|
||||
let nym_api_client = nym_http_api_client::Client::new(config.api_url.clone(), None);
|
||||
|
||||
Client {
|
||||
nym_api: nym_api_client,
|
||||
@@ -385,38 +385,25 @@ impl<C, S> Client<C, S> {
|
||||
}
|
||||
}
|
||||
|
||||
/// DEPRECATED: Use nym_http_api_client::Client with from_network() or with_bincode() instead
|
||||
#[deprecated(
|
||||
since = "1.2.0",
|
||||
note = "Use nym_http_api_client::Client::from_network() or ClientBuilder::with_bincode() instead"
|
||||
)]
|
||||
#[derive(Clone)]
|
||||
pub struct NymApiClient {
|
||||
pub use_bincode: bool,
|
||||
pub nym_api: nym_api::Client,
|
||||
pub nym_api: nym_http_api_client::Client,
|
||||
// TODO: perhaps if we really need it at some (currently I don't see any reasons for it)
|
||||
// we could re-implement the communication with the REST API on port 1317
|
||||
}
|
||||
|
||||
impl From<nym_api::Client> for NymApiClient {
|
||||
fn from(nym_api: nym_api::Client) -> Self {
|
||||
NymApiClient {
|
||||
use_bincode: false,
|
||||
nym_api,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have to allow the use of deprecated method here as they're calling the deprecated trait methods
|
||||
#[allow(deprecated)]
|
||||
impl NymApiClient {
|
||||
pub fn new(api_url: Url) -> Self {
|
||||
let nym_api = nym_api::Client::new(api_url, None);
|
||||
|
||||
NymApiClient {
|
||||
use_bincode: true,
|
||||
nym_api,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn new_with_timeout(api_url: Url, timeout: std::time::Duration) -> Self {
|
||||
let nym_api = nym_api::Client::new(api_url, Some(timeout));
|
||||
let nym_api = nym_http_api_client::Client::new(api_url, Some(timeout));
|
||||
|
||||
NymApiClient {
|
||||
use_bincode: true,
|
||||
@@ -431,10 +418,10 @@ impl NymApiClient {
|
||||
}
|
||||
|
||||
pub fn new_with_user_agent(api_url: Url, user_agent: impl Into<UserAgent>) -> Self {
|
||||
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
|
||||
let nym_api = nym_http_api_client::Client::builder(api_url)
|
||||
.expect("invalid api url")
|
||||
.with_user_agent(user_agent.into())
|
||||
.build::<ValidatorClientError>()
|
||||
.build()
|
||||
.expect("failed to build nym api client");
|
||||
|
||||
NymApiClient {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use crate::nyxd::contract_traits::{DkgQueryClient, PagedDkgQueryClient};
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::NymApiClient;
|
||||
use nym_coconut_dkg_common::types::{EpochId, NodeIndex};
|
||||
use nym_coconut_dkg_common::verification_key::ContractVKShare;
|
||||
use nym_compact_ecash::error::CompactEcashError;
|
||||
@@ -15,7 +14,7 @@ use url::Url;
|
||||
// TODO: it really doesn't feel like this should live in this crate.
|
||||
#[derive(Clone)]
|
||||
pub struct EcashApiClient {
|
||||
pub api_client: NymApiClient,
|
||||
pub api_client: nym_http_api_client::Client,
|
||||
pub verification_key: VerificationKeyAuth,
|
||||
pub node_id: NodeIndex,
|
||||
pub cosmos_address: cosmrs::AccountId,
|
||||
@@ -25,10 +24,15 @@ impl Display for EcashApiClient {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"[id: {}] {} @ {}",
|
||||
"[id: {}] {} @ ({})",
|
||||
self.node_id,
|
||||
self.cosmos_address,
|
||||
self.api_client.api_url()
|
||||
self.api_client
|
||||
.base_urls()
|
||||
.iter()
|
||||
.map(|url| url.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -60,6 +64,9 @@ pub enum EcashApiError {
|
||||
source: CompactEcashError,
|
||||
},
|
||||
|
||||
#[error("failed to create API client: {0}")]
|
||||
ClientError(String),
|
||||
|
||||
#[error("the provided account address is malformed: {source}")]
|
||||
MalformedAccountAddress {
|
||||
#[from]
|
||||
@@ -89,8 +96,13 @@ impl TryFrom<ContractVKShare> for EcashApiClient {
|
||||
// In non-client applications this resolver can cause warning logs about H2 connection
|
||||
// failure. This indicates that the long lived https connection was closed by the remote
|
||||
// peer and the resolver will have to reconnect. It should not impact actual functionality
|
||||
let api_client = nym_http_api_client::Client::builder(url_address)
|
||||
.map_err(|e| EcashApiError::ClientError(e.to_string()))?
|
||||
.build()
|
||||
.map_err(|e| EcashApiError::ClientError(e.to_string()))?;
|
||||
|
||||
Ok(EcashApiClient {
|
||||
api_client: NymApiClient::new(url_address),
|
||||
api_client,
|
||||
verification_key: VerificationKeyAuth::try_from_bs58(&share.share)?,
|
||||
node_id: share.node_index,
|
||||
cosmos_address: share.owner.as_str().parse()?,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::nym_api::NymApiClientExt;
|
||||
use crate::nyxd::contract_traits::MixnetQueryClient;
|
||||
use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::Config as ClientConfig;
|
||||
use crate::{NymApiClient, QueryHttpRpcNyxdClient, ValidatorClientError};
|
||||
use crate::{QueryHttpRpcNyxdClient, ValidatorClientError};
|
||||
use colored::Colorize;
|
||||
use core::fmt;
|
||||
use itertools::Itertools;
|
||||
@@ -87,8 +88,17 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
|
||||
}
|
||||
});
|
||||
|
||||
let api_connection_test_clients = api_urls.map(|(network, url)| {
|
||||
ClientForConnectionTest::Api(network, url.clone(), NymApiClient::new(url))
|
||||
let api_connection_test_clients = api_urls.filter_map(|(network, url)| {
|
||||
match nym_http_api_client::Client::builder(url.clone()).and_then(|b| b.build()) {
|
||||
Ok(client) => Some(ClientForConnectionTest::Api(network, url, client)),
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
"Failed to create API client for {}: {err}",
|
||||
network.network_name
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
nyxd_connection_test_clients.chain(api_connection_test_clients)
|
||||
@@ -160,7 +170,7 @@ async fn test_nyxd_connection(
|
||||
async fn test_nym_api_connection(
|
||||
network: NymNetworkDetails,
|
||||
url: &Url,
|
||||
client: &NymApiClient,
|
||||
client: &nym_http_api_client::Client,
|
||||
) -> ConnectionResult {
|
||||
let result = match timeout(
|
||||
Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC),
|
||||
@@ -186,7 +196,7 @@ async fn test_nym_api_connection(
|
||||
|
||||
enum ClientForConnectionTest {
|
||||
Nyxd(NymNetworkDetails, Url, Box<QueryHttpRpcNyxdClient>),
|
||||
Api(NymNetworkDetails, Url, NymApiClient),
|
||||
Api(NymNetworkDetails, Url, nym_http_api_client::Client),
|
||||
}
|
||||
|
||||
impl ClientForConnectionTest {
|
||||
|
||||
@@ -14,7 +14,6 @@ pub mod signing;
|
||||
pub use crate::error::ValidatorClientError;
|
||||
pub use crate::rpc::reqwest::ReqwestRpcClient;
|
||||
pub use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
|
||||
pub use client::NymApiClient;
|
||||
pub use client::{Client, Config, EcashApiClient};
|
||||
pub use nym_api_requests::*;
|
||||
pub use nym_http_api_client::UserAgent;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_api_requests::models::RequestError;
|
||||
use nym_http_api_client::HttpClientError;
|
||||
|
||||
pub type NymAPIError = HttpClientError<RequestError>;
|
||||
pub type NymAPIError = HttpClientError;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::nym_api::error::NymAPIError;
|
||||
use crate::nym_api::routes::{ecash, CORE_STATUS_COUNT, SINCE_ARG};
|
||||
use crate::nym_nodes::SkimmedNodesWithMetadata;
|
||||
use async_trait::async_trait;
|
||||
use nym_api_requests::ecash::models::{
|
||||
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
|
||||
@@ -37,7 +38,7 @@ pub use nym_api_requests::{
|
||||
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
|
||||
StakeSaturationResponse, UptimeResponse,
|
||||
},
|
||||
nym_nodes::{CachedNodesResponse, SemiSkimmedNode, SkimmedNode},
|
||||
nym_nodes::{CachedNodesResponse, SemiSkimmedNode, SemiSkimmedNodesWithMetadata, SkimmedNode},
|
||||
NymNetworkDetailsResponse,
|
||||
};
|
||||
use nym_contracts_common::IdentityKey;
|
||||
@@ -49,8 +50,8 @@ use time::format_description::BorrowedFormatItem;
|
||||
use time::Date;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::ValidatorClientError;
|
||||
pub use nym_coconut_dkg_common::types::EpochId;
|
||||
pub use nym_http_api_client::Client;
|
||||
|
||||
pub mod error;
|
||||
pub mod routes;
|
||||
@@ -62,6 +63,9 @@ pub fn rfc_3339_date() -> Vec<BorrowedFormatItem<'static>> {
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait NymApiClientExt: ApiClient {
|
||||
/// Get the current API URL being used by the client
|
||||
fn api_url(&self) -> &url::Url;
|
||||
|
||||
async fn health(&self) -> Result<ApiHealthResponse, NymAPIError> {
|
||||
self.get_json(
|
||||
&[
|
||||
@@ -241,6 +245,156 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_current_rewarded_set(&self) -> Result<RewardedSetResponse, NymAPIError> {
|
||||
self.get_rewarded_set().await
|
||||
}
|
||||
|
||||
async fn get_all_basic_nodes_with_metadata(
|
||||
&self,
|
||||
) -> Result<SkimmedNodesWithMetadata, NymAPIError> {
|
||||
// unroll first loop iteration in order to obtain the metadata
|
||||
let mut page = 0;
|
||||
let res = self
|
||||
.get_basic_nodes_v2(false, Some(page), None, true)
|
||||
.await?;
|
||||
let mut nodes = res.nodes.data;
|
||||
let metadata = res.metadata;
|
||||
|
||||
if res.nodes.pagination.total == nodes.len() {
|
||||
return Ok(SkimmedNodesWithMetadata::new(nodes, metadata));
|
||||
}
|
||||
|
||||
page += 1;
|
||||
|
||||
loop {
|
||||
let mut res = self
|
||||
.get_basic_nodes_v2(false, Some(page), None, true)
|
||||
.await?;
|
||||
|
||||
if !metadata.consistency_check(&res.metadata) {
|
||||
// Create a custom error for inconsistent metadata
|
||||
return Err(NymAPIError::InternalResponseInconsistency {
|
||||
url: self.api_url().clone(),
|
||||
details: "Inconsistent paged metadata".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
nodes.append(&mut res.nodes.data);
|
||||
if nodes.len() >= res.nodes.pagination.total {
|
||||
break;
|
||||
} else {
|
||||
page += 1
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SkimmedNodesWithMetadata::new(nodes, metadata))
|
||||
}
|
||||
|
||||
async fn get_all_basic_active_mixing_assigned_nodes_with_metadata(
|
||||
&self,
|
||||
) -> Result<SkimmedNodesWithMetadata, NymAPIError> {
|
||||
// Get all mixing nodes that are in the active/rewarded set
|
||||
let mut page = 0;
|
||||
let res = self
|
||||
.get_basic_active_mixing_assigned_nodes_v2(false, Some(page), None, false)
|
||||
.await?;
|
||||
|
||||
let metadata = res.metadata;
|
||||
let mut nodes = res.nodes.data;
|
||||
|
||||
if res.nodes.pagination.total == nodes.len() {
|
||||
return Ok(SkimmedNodesWithMetadata::new(nodes, metadata));
|
||||
}
|
||||
|
||||
page += 1;
|
||||
|
||||
loop {
|
||||
let res = self
|
||||
.get_basic_active_mixing_assigned_nodes_v2(false, Some(page), None, false)
|
||||
.await?;
|
||||
|
||||
if !metadata.consistency_check(&res.metadata) {
|
||||
return Err(NymAPIError::InternalResponseInconsistency {
|
||||
url: self.api_url().clone(),
|
||||
details: "Inconsistent paged metadata".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
nodes.append(&mut res.nodes.data.clone());
|
||||
|
||||
// Check if we've got all nodes
|
||||
if nodes.len() >= res.nodes.pagination.total {
|
||||
break;
|
||||
} else {
|
||||
page += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SkimmedNodesWithMetadata::new(nodes, metadata))
|
||||
}
|
||||
|
||||
async fn get_all_basic_entry_assigned_nodes_with_metadata(
|
||||
&self,
|
||||
) -> Result<SkimmedNodesWithMetadata, NymAPIError> {
|
||||
// Get all nodes that can act as entry gateways
|
||||
let mut page = 0;
|
||||
let res = self
|
||||
.get_basic_entry_assigned_nodes_v2(false, Some(page), None, false)
|
||||
.await?;
|
||||
|
||||
let metadata = res.metadata;
|
||||
let mut nodes = res.nodes.data;
|
||||
|
||||
if res.nodes.pagination.total == nodes.len() {
|
||||
return Ok(SkimmedNodesWithMetadata::new(nodes, metadata));
|
||||
}
|
||||
|
||||
page += 1;
|
||||
|
||||
loop {
|
||||
let res = self
|
||||
.get_basic_entry_assigned_nodes_v2(false, Some(page), None, false)
|
||||
.await?;
|
||||
|
||||
if !metadata.consistency_check(&res.metadata) {
|
||||
return Err(NymAPIError::InternalResponseInconsistency {
|
||||
url: self.api_url().clone(),
|
||||
details: "Inconsistent paged metadata".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
nodes.append(&mut res.nodes.data.clone());
|
||||
|
||||
// Check if we've got all nodes
|
||||
if nodes.len() >= res.nodes.pagination.total {
|
||||
break;
|
||||
} else {
|
||||
page += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SkimmedNodesWithMetadata::new(nodes, metadata))
|
||||
}
|
||||
|
||||
async fn get_all_described_nodes(&self) -> Result<Vec<NymNodeDescription>, NymAPIError> {
|
||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
let mut page = 0;
|
||||
let mut descriptions = Vec::new();
|
||||
|
||||
loop {
|
||||
let mut res = self.get_nodes_described(Some(page), None).await?;
|
||||
|
||||
descriptions.append(&mut res.data);
|
||||
if descriptions.len() < res.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(descriptions)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn get_nym_nodes(
|
||||
&self,
|
||||
@@ -268,6 +422,25 @@ pub trait NymApiClientExt: ApiClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_all_bonded_nym_nodes(&self) -> Result<Vec<NymNodeDetails>, ValidatorClientError> {
|
||||
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
|
||||
let mut page = 0;
|
||||
let mut bonds = Vec::new();
|
||||
|
||||
loop {
|
||||
let mut res = self.get_nym_nodes(Some(page), None).await?;
|
||||
|
||||
bonds.append(&mut res.data);
|
||||
if bonds.len() < res.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(bonds)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn get_basic_mixnodes(&self) -> Result<CachedNodesResponse<SkimmedNode>, NymAPIError> {
|
||||
@@ -1371,8 +1544,49 @@ pub trait NymApiClientExt: ApiClient {
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Method to change the base API URLs being used by the client
|
||||
fn change_base_urls(&mut self, urls: Vec<url::Url>);
|
||||
|
||||
/// Retrieve expanded information for all bonded nodes on the network
|
||||
async fn get_all_expanded_nodes(&self) -> Result<SemiSkimmedNodesWithMetadata, NymAPIError> {
|
||||
// Unroll the first iteration to get the metadata
|
||||
let mut page = 0;
|
||||
|
||||
let res = self.get_expanded_nodes(false, Some(page), None).await?;
|
||||
let mut nodes = res.nodes.data;
|
||||
let metadata = res.metadata;
|
||||
|
||||
if res.nodes.pagination.total == nodes.len() {
|
||||
return Ok(SemiSkimmedNodesWithMetadata::new(nodes, metadata));
|
||||
}
|
||||
|
||||
page += 1;
|
||||
|
||||
loop {
|
||||
let mut res = self.get_expanded_nodes(false, Some(page), None).await?;
|
||||
|
||||
nodes.append(&mut res.nodes.data);
|
||||
if nodes.len() < res.nodes.pagination.total {
|
||||
page += 1
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SemiSkimmedNodesWithMetadata::new(nodes, metadata))
|
||||
}
|
||||
}
|
||||
|
||||
// Client is already nym_http_api_client::Client (re-exported above), so just one impl needed
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
impl NymApiClientExt for Client {}
|
||||
impl NymApiClientExt for nym_http_api_client::Client {
|
||||
fn api_url(&self) -> &url::Url {
|
||||
self.current_url().as_ref()
|
||||
}
|
||||
|
||||
fn change_base_urls(&mut self, urls: Vec<url::Url>) {
|
||||
self.change_base_urls(urls.into_iter().map(|u| u.into()).collect());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ cosmrs = { workspace = true }
|
||||
cosmwasm-std = { workspace = true }
|
||||
|
||||
nym-validator-client = { path = "../client-libs/validator-client" }
|
||||
nym-http-api-client = { path = "../http-api-client" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::context::errors::ContextError;
|
||||
pub use nym_http_api_client::Client as NymApiClient;
|
||||
use nym_network_defaults::{
|
||||
setup_env,
|
||||
var_names::{MIXNET_CONTRACT_ADDRESS, NYM_API, NYXD, VESTING_CONTRACT_ADDRESS},
|
||||
NymNetworkDetails,
|
||||
};
|
||||
pub use nym_validator_client::nym_api::Client as NymApiClient;
|
||||
use nym_validator_client::nyxd::{self, AccountId, NyxdClient};
|
||||
use nym_validator_client::{
|
||||
DirectSigningHttpRpcNyxdClient, DirectSigningHttpRpcValidatorClient, QueryHttpRpcNyxdClient,
|
||||
|
||||
@@ -14,7 +14,7 @@ use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketB
|
||||
use nym_credentials_interface::Bandwidth;
|
||||
use nym_credentials_interface::{ClientTicket, TicketType};
|
||||
use nym_validator_client::coconut::EcashApiError;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nym_api::{EpochId, NymApiClientExt};
|
||||
use nym_validator_client::nyxd::contract_traits::{
|
||||
EcashSigningClient, MultisigQueryClient, MultisigSigningClient, PagedMultisigQueryClient,
|
||||
};
|
||||
@@ -354,7 +354,7 @@ impl CredentialHandler {
|
||||
Err(err) => {
|
||||
error!("failed to send ticket {ticket_id} for verification to ecash signer '{client}': {err}. if we don't reach quorum, we'll retry later");
|
||||
Err(EcashTicketError::ApiFailure(EcashApiError::NymApi {
|
||||
source: err,
|
||||
source: nym_validator_client::ValidatorClientError::NymAPIError { source: err },
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ nym-ecash-time = { path = "../ecash-time", features = ["expiration"] }
|
||||
nym-credentials-interface = { path = "../credentials-interface" }
|
||||
nym-crypto = { path = "../crypto" }
|
||||
nym-api-requests = { path = "../../nym-api/nym-api-requests" }
|
||||
nym-http-api-client = { path = "../http-api-client" }
|
||||
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
|
||||
nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
|
||||
@@ -15,7 +15,7 @@ use nym_credentials_interface::{
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_ecash_contract_common::deposit::DepositId;
|
||||
use nym_ecash_time::{ecash_default_expiration_date, ecash_today, EcashTime};
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nym_api::{EpochId, NymApiClientExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::Date;
|
||||
|
||||
@@ -116,7 +116,7 @@ impl IssuanceTicketBook {
|
||||
|
||||
pub async fn obtain_blinded_credential(
|
||||
&self,
|
||||
client: &nym_validator_client::client::NymApiClient,
|
||||
client: &nym_http_api_client::Client,
|
||||
request_body: &BlindSignRequestBody,
|
||||
) -> Result<BlindedSignature, Error> {
|
||||
let server_response = client.blind_sign(request_body).await?;
|
||||
@@ -179,7 +179,7 @@ impl IssuanceTicketBook {
|
||||
// ideally this would have been generic over credential type, but we really don't need secp256k1 keys for bandwidth vouchers
|
||||
pub async fn obtain_partial_ticketbook_credential(
|
||||
&self,
|
||||
client: &nym_validator_client::client::NymApiClient,
|
||||
client: &nym_http_api_client::Client,
|
||||
signer_index: u64,
|
||||
validator_vk: &VerificationKeyAuth,
|
||||
signing_data: CredentialSigningData,
|
||||
|
||||
@@ -10,6 +10,7 @@ use nym_credentials_interface::{
|
||||
VerificationKeyAuth, WalletSignatures,
|
||||
};
|
||||
use nym_validator_client::client::EcashApiClient;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
|
||||
// so we wouldn't break all the existing imports
|
||||
pub use nym_ecash_time::{cred_exp_date, ecash_date_offset, ecash_today, EcashTime};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::ecash::bandwidth::issued::CURRENT_SERIALIZATION_REVISION;
|
||||
use nym_credentials_interface::CompactEcashError;
|
||||
use nym_crypto::asymmetric::x25519::KeyRecoveryError;
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use nym_validator_client::{nym_api::error::NymAPIError, ValidatorClientError};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -37,6 +37,9 @@ pub enum Error {
|
||||
#[error("Ran into a validator client error - {0}")]
|
||||
ValidatorClientError(#[from] ValidatorClientError),
|
||||
|
||||
#[error("Nym API request failed - {0}")]
|
||||
NymAPIError(#[from] NymAPIError),
|
||||
|
||||
#[error("Bandwidth operation overflowed. {0}")]
|
||||
BandwidthOverflow(String),
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ url = { workspace = true }
|
||||
nym-validator-client = { path = "../client-libs/validator-client" }
|
||||
nym-network-defaults = { path = "../network-defaults" }
|
||||
nym-ecash-signer-check-types = { path = "../ecash-signer-check-types" }
|
||||
nym-http-api-client = { path = "../http-api-client" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{LocalChainStatus, SigningStatus, TypedSignerResult};
|
||||
use crate::{LocalChainStatus, SignerCheckError, SigningStatus, TypedSignerResult};
|
||||
use nym_ecash_signer_check_types::dealer_information::RawDealerInformation;
|
||||
use nym_ecash_signer_check_types::status::{SignerStatus, SignerTestResult};
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::models::BinaryBuildInformationOwned;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::nyxd::contract_traits::dkg_query_client::{
|
||||
ContractVKShare, DealerDetails,
|
||||
};
|
||||
use nym_validator_client::NymApiClient;
|
||||
use std::time::Duration;
|
||||
use tracing::{error, warn};
|
||||
use url::Url;
|
||||
@@ -32,37 +31,38 @@ pub(crate) mod signing_status {
|
||||
}
|
||||
|
||||
struct ClientUnderTest {
|
||||
api_client: NymApiClient,
|
||||
api_client: nym_http_api_client::Client,
|
||||
build_info: Option<BinaryBuildInformationOwned>,
|
||||
}
|
||||
|
||||
impl ClientUnderTest {
|
||||
pub(crate) fn new(api_url: &Url) -> Self {
|
||||
ClientUnderTest {
|
||||
api_client: NymApiClient::new(api_url.clone()),
|
||||
pub(crate) fn new(api_url: &Url) -> Result<Self, SignerCheckError> {
|
||||
// The builder should not fail with a valid URL that's already parsed
|
||||
// If it does fail, it's an internal error that we can't recover from
|
||||
let api_client = nym_http_api_client::Client::builder(api_url.clone())?.build()?;
|
||||
|
||||
Ok(ClientUnderTest {
|
||||
api_client,
|
||||
build_info: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn try_retrieve_build_information(&mut self) -> bool {
|
||||
match tokio::time::timeout(
|
||||
Duration::from_secs(5),
|
||||
self.api_client.nym_api.build_information(),
|
||||
)
|
||||
.await
|
||||
match tokio::time::timeout(Duration::from_secs(5), self.api_client.build_information())
|
||||
.await
|
||||
{
|
||||
Ok(Ok(build_information)) => {
|
||||
self.build_info = Some(build_information);
|
||||
true
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
warn!("{}: failed to retrieve build information: {err}. the signer is most likely down", self.api_client.api_url());
|
||||
warn!("{}: failed to retrieve build information: {err}. the signer is most likely down", self.api_client.current_url());
|
||||
false
|
||||
}
|
||||
Err(_timeout) => {
|
||||
warn!(
|
||||
"{}: timed out while attempting to retrieve build information",
|
||||
self.api_client.api_url()
|
||||
self.api_client.current_url()
|
||||
);
|
||||
false
|
||||
}
|
||||
@@ -77,7 +77,7 @@ impl ClientUnderTest {
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
"ecash signer '{}' reports invalid version {}: {err}",
|
||||
self.api_client.api_url(),
|
||||
self.api_client.current_url(),
|
||||
build_info.build_version
|
||||
)
|
||||
})
|
||||
@@ -121,14 +121,14 @@ impl ClientUnderTest {
|
||||
|
||||
// check if it supports the current query
|
||||
if self.supports_chain_status_query() {
|
||||
return match self.api_client.nym_api.get_chain_blocks_status().await {
|
||||
return match self.api_client.get_chain_blocks_status().await {
|
||||
Ok(status) => LocalChainStatus::Reachable {
|
||||
response: Box::new(status),
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"{}: failed to retrieve local chain status: {err}",
|
||||
self.api_client.api_url()
|
||||
self.api_client.current_url()
|
||||
);
|
||||
LocalChainStatus::Unreachable
|
||||
}
|
||||
@@ -136,14 +136,14 @@ impl ClientUnderTest {
|
||||
}
|
||||
|
||||
// fallback to the legacy query
|
||||
match self.api_client.nym_api.get_chain_status().await {
|
||||
match self.api_client.get_chain_status().await {
|
||||
Ok(status) => LocalChainStatus::ReachableLegacy {
|
||||
response: Box::new(status),
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"{}: failed to retrieve [legacy] local chain status: {err}",
|
||||
self.api_client.api_url()
|
||||
self.api_client.current_url()
|
||||
);
|
||||
LocalChainStatus::Unreachable
|
||||
}
|
||||
@@ -158,14 +158,14 @@ impl ClientUnderTest {
|
||||
|
||||
// check if it supports the current query
|
||||
if self.supports_signing_status_query() {
|
||||
return match self.api_client.nym_api.get_signer_status().await {
|
||||
return match self.api_client.get_signer_status().await {
|
||||
Ok(response) => SigningStatus::Reachable {
|
||||
response: Box::new(response),
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"{}: failed to retrieve signer chain status: {err}",
|
||||
self.api_client.api_url()
|
||||
self.api_client.current_url()
|
||||
);
|
||||
SigningStatus::Unreachable
|
||||
}
|
||||
@@ -173,14 +173,14 @@ impl ClientUnderTest {
|
||||
}
|
||||
|
||||
// fallback to the legacy query
|
||||
match self.api_client.nym_api.get_signer_information().await {
|
||||
match self.api_client.get_signer_information().await {
|
||||
Ok(status) => SigningStatus::ReachableLegacy {
|
||||
response: Box::new(status),
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(
|
||||
"{}: failed to retrieve [legacy] signer chain status: {err}",
|
||||
self.api_client.api_url()
|
||||
self.api_client.current_url()
|
||||
);
|
||||
// NOTE: this might equally mean the signing is disabled
|
||||
SigningStatus::Unreachable
|
||||
@@ -201,7 +201,13 @@ pub(crate) async fn check_client(
|
||||
return SignerStatus::ProvidedInvalidDetails.with_details(dealer_information, dkg_epoch);
|
||||
};
|
||||
|
||||
let mut client = ClientUnderTest::new(&parsed_information.announce_address);
|
||||
let mut client = match ClientUnderTest::new(&parsed_information.announce_address) {
|
||||
Ok(client) => client,
|
||||
Err(err) => {
|
||||
error!("failed to create client instance: {err}");
|
||||
return SignerStatus::Unreachable.with_details(dealer_information, dkg_epoch);
|
||||
}
|
||||
};
|
||||
|
||||
// 8. check basic connection status - can you retrieve build information?
|
||||
if !client.try_retrieve_build_information().await {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_http_api_client::HttpClientError;
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -11,6 +12,12 @@ pub enum SignerCheckError {
|
||||
|
||||
#[error("failed to query the DKG contract: {source}")]
|
||||
DKGContractQueryFailure { source: NyxdError },
|
||||
|
||||
#[error("failed to build client: {source}")]
|
||||
HttpClient {
|
||||
#[from]
|
||||
source: HttpClientError,
|
||||
},
|
||||
}
|
||||
|
||||
impl SignerCheckError {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "nym-http-api-client-macro"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
rust-version.workspace = true
|
||||
readme.workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1"
|
||||
syn = { workspace = true, features = ["full"] }
|
||||
quote = "1.0.40"
|
||||
proc-macro-crate = "3"
|
||||
|
||||
[dev-dependencies]
|
||||
nym-http-api-client = { path = "../http-api-client" }
|
||||
reqwest = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
@@ -0,0 +1,311 @@
|
||||
//! Proc-macros for configuring HTTP clients globally via the `inventory` crate.
|
||||
//!
|
||||
//! This crate provides macros that allow any crate in the workspace to contribute
|
||||
//! configuration modifications to `reqwest::ClientBuilder` instances through a
|
||||
//! compile-time registry pattern.
|
||||
//!
|
||||
//! # Overview
|
||||
//!
|
||||
//! The macros work by:
|
||||
//! 1. Collecting configuration functions from across all crates at compile time
|
||||
//! 2. Sorting them by priority (lower numbers run first)
|
||||
//! 3. Applying them sequentially to build HTTP clients with consistent settings
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ## Basic Usage with `client_defaults!`
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use nym_http_api_client_macro::client_defaults;
|
||||
//!
|
||||
//! // Register default configurations with priority
|
||||
//! client_defaults!(
|
||||
//! priority = 10; // Optional, defaults to 0
|
||||
//! timeout = std::time::Duration::from_secs(30),
|
||||
//! gzip = true,
|
||||
//! user_agent = "MyApp/1.0"
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
//! ## Using `client_cfg!` for one-off configurations
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use nym_http_api_client_macro::client_cfg;
|
||||
//!
|
||||
//! let configure = client_cfg!(
|
||||
//! timeout = std::time::Duration::from_secs(60),
|
||||
//! default_headers {
|
||||
//! "X-Custom-Header" => "value",
|
||||
//! "Authorization" => auth_token
|
||||
//! }
|
||||
//! );
|
||||
//!
|
||||
//! let builder = reqwest::ClientBuilder::new();
|
||||
//! let configured = configure(builder);
|
||||
//! ```
|
||||
//!
|
||||
//! # DSL Reference
|
||||
//!
|
||||
//! The macro DSL supports several patterns:
|
||||
//! - `key = value` - Calls `builder.key(value)`
|
||||
//! - `key(arg1, arg2)` - Calls `builder.key(arg1, arg2)`
|
||||
//! - `flag` - Calls `builder.flag()` with no arguments
|
||||
//! - `default_headers { "name" => "value", ... }` - Sets default headers
|
||||
//!
|
||||
//! # Priority System
|
||||
//!
|
||||
//! Configurations are applied in priority order (lower numbers first):
|
||||
//! - Negative priorities: Early configuration (e.g., -100 for base settings)
|
||||
//! - Zero (default): Standard configuration
|
||||
//! - Positive priorities: Late configuration (e.g., 100 for overrides)
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
braced,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_macro_input,
|
||||
punctuated::Punctuated,
|
||||
token, Expr, Ident, LitInt, Result, Token,
|
||||
};
|
||||
|
||||
// ------------------ core crate path resolution ------------------
|
||||
|
||||
fn core_path() -> TokenStream2 {
|
||||
match crate_name("nym-http-api-client") {
|
||||
Ok(FoundCrate::Itself) => quote!(crate),
|
||||
Ok(FoundCrate::Name(name)) => {
|
||||
let ident = Ident::new(&name, Span::call_site());
|
||||
quote!( ::#ident )
|
||||
}
|
||||
Err(_) => {
|
||||
// Fallback if the crate is not found by name (unlikely if deps set up correctly)
|
||||
quote!(::nym_http_api_client)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ DSL parsing ------------------
|
||||
|
||||
struct Items(Punctuated<Item, Token![,]>);
|
||||
impl Parse for Items {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
Ok(Self(Punctuated::parse_terminated(input)?))
|
||||
}
|
||||
}
|
||||
|
||||
enum Item {
|
||||
Assign {
|
||||
key: Ident,
|
||||
_eq: Token![=],
|
||||
value: Expr,
|
||||
}, // foo = EXPR
|
||||
Call {
|
||||
key: Ident,
|
||||
args: Punctuated<Expr, Token![,]>,
|
||||
_p: token::Paren,
|
||||
}, // foo(a,b)
|
||||
DefaultHeaders {
|
||||
_key: Ident,
|
||||
map: HeaderMapInit,
|
||||
}, // default_headers { ... }
|
||||
Flag {
|
||||
key: Ident,
|
||||
}, // foo
|
||||
}
|
||||
|
||||
impl Parse for Item {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let key: Ident = input.parse()?;
|
||||
|
||||
if input.peek(Token![=]) {
|
||||
let _eq: Token![=] = input.parse()?;
|
||||
let value: Expr = input.parse()?;
|
||||
return Ok(Self::Assign { key, _eq, value });
|
||||
}
|
||||
if input.peek(token::Paren) {
|
||||
let content;
|
||||
let _p = syn::parenthesized!(content in input);
|
||||
let args = Punctuated::<Expr, Token![,]>::parse_terminated(&content)?;
|
||||
return Ok(Self::Call { key, args, _p });
|
||||
}
|
||||
if input.peek(token::Brace) && key == format_ident!("default_headers") {
|
||||
let map = input.parse::<HeaderMapInit>()?;
|
||||
return Ok(Self::DefaultHeaders { _key: key, map });
|
||||
}
|
||||
Ok(Self::Flag { key })
|
||||
}
|
||||
}
|
||||
|
||||
struct HeaderPair {
|
||||
k: Expr,
|
||||
_arrow: Token![=>],
|
||||
v: Expr,
|
||||
}
|
||||
impl Parse for HeaderPair {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
k: input.parse()?,
|
||||
_arrow: input.parse()?,
|
||||
v: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct HeaderMapInit {
|
||||
_brace: token::Brace,
|
||||
pairs: Punctuated<HeaderPair, Token![,]>,
|
||||
}
|
||||
impl Parse for HeaderMapInit {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let content;
|
||||
let _brace = braced!(content in input);
|
||||
let pairs = Punctuated::<HeaderPair, Token![,]>::parse_terminated(&content)?;
|
||||
Ok(Self { _brace, pairs })
|
||||
}
|
||||
}
|
||||
|
||||
// Generate statements that mutate a builder named `b` using the resolved core path.
|
||||
fn to_stmts(items: Items, core: &TokenStream2) -> TokenStream2 {
|
||||
let mut stmts = Vec::new();
|
||||
for it in items.0 {
|
||||
match it {
|
||||
Item::Assign { key, value, .. } => {
|
||||
let m = key;
|
||||
stmts.push(quote! { b = b.#m(#value); });
|
||||
}
|
||||
Item::Call { key, args, .. } => {
|
||||
let m = key;
|
||||
let args = args.iter();
|
||||
stmts.push(quote! { b = b.#m( #( #args ),* ); });
|
||||
}
|
||||
Item::DefaultHeaders { map, .. } => {
|
||||
let (ks, vs): (Vec<_>, Vec<_>) = map.pairs.into_iter().map(|p| (p.k, p.v)).unzip();
|
||||
stmts.push(quote! {
|
||||
let mut __cm = #core::reqwest::header::HeaderMap::new();
|
||||
#(
|
||||
{
|
||||
use #core::reqwest::header::{HeaderName, HeaderValue};
|
||||
let __k = HeaderName::try_from(#ks)
|
||||
.unwrap_or_else(|e| panic!("Invalid header name: {}", e));
|
||||
let __v = HeaderValue::try_from(#vs)
|
||||
.unwrap_or_else(|e| panic!("Invalid header value: {}", e));
|
||||
__cm.insert(__k, __v);
|
||||
}
|
||||
)*
|
||||
b = b.default_headers(__cm);
|
||||
});
|
||||
}
|
||||
Item::Flag { key } => {
|
||||
let m = key;
|
||||
stmts.push(quote! { b = b.#m(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
quote! { #(#stmts)* }
|
||||
}
|
||||
|
||||
// ------------------ client_cfg! ------------------
|
||||
|
||||
/// Creates a closure that configures a `ReqwestClientBuilder`.
|
||||
///
|
||||
/// This macro generates a closure that can be used to configure a single
|
||||
/// `reqwest::ClientBuilder` instance without affecting global defaults.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// let config = client_cfg!(
|
||||
/// timeout = Duration::from_secs(30),
|
||||
/// gzip = true
|
||||
/// );
|
||||
/// let client = config(reqwest::ClientBuilder::new()).build()?;
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn client_cfg(input: TokenStream) -> TokenStream {
|
||||
let items = parse_macro_input!(input as Items);
|
||||
let core = core_path();
|
||||
let body = to_stmts(items, &core);
|
||||
let out = quote! {
|
||||
|mut b: #core::ReqwestClientBuilder| { #body b }
|
||||
};
|
||||
out.into()
|
||||
}
|
||||
|
||||
// ------------------ client_defaults! with optional priority header ------------------
|
||||
|
||||
struct MaybePrioritized {
|
||||
priority: i32,
|
||||
items: Items,
|
||||
}
|
||||
impl Parse for MaybePrioritized {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
// Optional header: `priority = <int> ;`
|
||||
let fork = input.fork();
|
||||
let mut priority = 0i32;
|
||||
if fork.peek(Ident) && fork.parse::<Ident>()? == "priority" && fork.peek(Token![=]) {
|
||||
// commit
|
||||
let _ = input.parse::<Ident>()?; // priority
|
||||
let _ = input.parse::<Token![=]>()?;
|
||||
let lit: LitInt = input.parse()?;
|
||||
priority = lit.base10_parse()?;
|
||||
let _ = input.parse::<Token![;]>()?;
|
||||
}
|
||||
let items = input.parse::<Items>()?;
|
||||
Ok(Self { priority, items })
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers global default configurations for HTTP clients.
|
||||
///
|
||||
/// This macro submits a configuration record to the global registry that will
|
||||
/// be applied to all HTTP clients created with `default_builder()`.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `priority` (optional): Integer priority for ordering (lower runs first, default: 0)
|
||||
/// - Configuration items: Any valid `reqwest::ClientBuilder` method calls
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// client_defaults!(
|
||||
/// priority = -50; // Run early in the configuration chain
|
||||
/// connect_timeout = Duration::from_secs(10),
|
||||
/// pool_max_idle_per_host = 32,
|
||||
/// default_headers {
|
||||
/// "User-Agent" => "MyApp/1.0",
|
||||
/// "Accept" => "application/json"
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn client_defaults(input: TokenStream) -> TokenStream {
|
||||
let MaybePrioritized { priority, items } = parse_macro_input!(input as MaybePrioritized);
|
||||
let core = core_path();
|
||||
let body = to_stmts(items, &core);
|
||||
|
||||
let out = quote! {
|
||||
#[allow(non_snake_case)]
|
||||
mod __client_defaults {
|
||||
use super::*;
|
||||
#[allow(unused)]
|
||||
pub fn __cfg(
|
||||
mut b: #core::ReqwestClientBuilder
|
||||
) -> #core::ReqwestClientBuilder {
|
||||
#body
|
||||
b
|
||||
}
|
||||
|
||||
#core::inventory::submit! {
|
||||
#core::registry::ConfigRecord {
|
||||
priority: #priority,
|
||||
apply: __cfg,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
out.into()
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
use nym_http_api_client_macro::{client_cfg, client_defaults};
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn test_client_cfg_basic() {
|
||||
// Test that the macro compiles with basic configuration
|
||||
let _config = client_cfg!(timeout = Duration::from_secs(30), gzip = true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_client_cfg_with_headers() {
|
||||
// Test that the macro compiles with default headers
|
||||
let _config = client_cfg!(
|
||||
timeout = Duration::from_secs(30),
|
||||
default_headers {
|
||||
"User-Agent" => "TestApp/1.0",
|
||||
"Accept" => "application/json"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_client_cfg_with_method_calls() {
|
||||
// Test that the macro compiles with method calls
|
||||
let _config = client_cfg!(
|
||||
pool_max_idle_per_host = 32,
|
||||
tcp_nodelay = true,
|
||||
danger_accept_invalid_certs = true
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_client_defaults_with_priority() {
|
||||
// Test that client_defaults macro compiles with priority
|
||||
client_defaults!(
|
||||
priority = -100;
|
||||
gzip = true,
|
||||
deflate = true
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_client_defaults_without_priority() {
|
||||
// Test that client_defaults macro compiles without priority (defaults to 0)
|
||||
client_defaults!(brotli = true, zstd = true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_client_cfg() {
|
||||
// Test that empty configuration compiles
|
||||
let _config = client_cfg!();
|
||||
}
|
||||
|
||||
// Integration test to verify the closure actually works
|
||||
#[test]
|
||||
fn test_client_cfg_closure_application() {
|
||||
let config = client_cfg!(gzip = true);
|
||||
|
||||
// Apply the configuration to a new builder
|
||||
let builder = reqwest::ClientBuilder::new();
|
||||
let _configured_builder = config(builder);
|
||||
// Note: We can't easily test the internal state of the builder,
|
||||
// but we verify it compiles and runs without panic
|
||||
}
|
||||
@@ -13,6 +13,7 @@ license.workspace = true
|
||||
[features]
|
||||
default=["tunneling"]
|
||||
tunneling=[]
|
||||
network-defaults = ["dep:nym-network-defaults"]
|
||||
|
||||
[dependencies]
|
||||
async-trait = { workspace = true }
|
||||
@@ -23,9 +24,12 @@ url = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde_yaml = { workspace = true}
|
||||
serde_plain = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
inventory = { workspace = true }
|
||||
|
||||
# used for decoding text responses (they were already implicitly included)
|
||||
bytes = { workspace = true }
|
||||
@@ -34,6 +38,8 @@ mime = { workspace = true }
|
||||
|
||||
nym-http-api-common = { path = "../http-api-common", default-features = false }
|
||||
nym-bin-common = { path = "../bin-common" }
|
||||
nym-network-defaults = { path = "../network-defaults", optional = true }
|
||||
nym-http-api-client-macro = { path = "../http-api-client-macro" }
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
|
||||
hickory-resolver = { workspace = true, features = ["https-ring", "tls-ring", "webpki-roots"] }
|
||||
|
||||
@@ -54,10 +54,14 @@ impl Front {
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
#[cfg(feature = "tunneling")]
|
||||
/// Policy for when to use domain fronting for HTTP requests.
|
||||
pub enum FrontPolicy {
|
||||
/// Always use domain fronting for all requests.
|
||||
Always,
|
||||
/// Only use domain fronting when retrying failed requests.
|
||||
OnRetry,
|
||||
#[default]
|
||||
/// Never use domain fronting.
|
||||
Off,
|
||||
}
|
||||
|
||||
@@ -96,14 +100,14 @@ mod tests {
|
||||
// Some(vec!["https://cdn77.com"]),
|
||||
// ).unwrap(); // cdn77
|
||||
|
||||
let client = ClientBuilder::new::<_, &str>(url1)
|
||||
let client = ClientBuilder::new(url1)
|
||||
.expect("bad url")
|
||||
.with_fronting(FrontPolicy::Always)
|
||||
.build::<&str>()
|
||||
.build()
|
||||
.expect("failed to build client");
|
||||
|
||||
let response = client
|
||||
.send_request::<_, (), &str, &str, &str>(
|
||||
.send_request::<_, (), &str, &str>(
|
||||
reqwest::Method::GET,
|
||||
&["api", "v1", "network", "details"],
|
||||
NO_PARAMS,
|
||||
|
||||
+418
-153
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
//! Global registry for HTTP client configurations.
|
||||
//!
|
||||
//! This module provides a compile-time registry system that allows any crate
|
||||
//! in the workspace to contribute configuration modifications to HTTP clients.
|
||||
|
||||
use crate::ReqwestClientBuilder;
|
||||
|
||||
/// A configuration record that modifies a `ReqwestClientBuilder`.
|
||||
///
|
||||
/// Records are collected at compile-time via the `inventory` crate and
|
||||
/// applied in priority order when building HTTP clients.
|
||||
pub struct ConfigRecord {
|
||||
/// Lower numbers run earlier.
|
||||
pub priority: i32,
|
||||
/// A function that takes a builder and returns a mutated builder.
|
||||
pub apply: fn(ReqwestClientBuilder) -> ReqwestClientBuilder,
|
||||
}
|
||||
|
||||
inventory::collect!(ConfigRecord);
|
||||
|
||||
/// Returns the default builder with all registered configurations applied.
|
||||
pub fn default_builder() -> ReqwestClientBuilder {
|
||||
let mut b = ReqwestClientBuilder::new();
|
||||
let mut records: Vec<&'static ConfigRecord> =
|
||||
inventory::iter::<ConfigRecord>.into_iter().collect();
|
||||
records.sort_by_key(|r| r.priority); // lower runs first
|
||||
for r in records {
|
||||
b = (r.apply)(b);
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
/// Builds a client using the default builder with all registered configurations.
|
||||
pub fn build_client() -> reqwest::Result<reqwest::Client> {
|
||||
default_builder().build()
|
||||
}
|
||||
|
||||
/// Debug function to inspect registered configurations.
|
||||
/// Returns a vector of (priority, function_pointer) tuples for debugging.
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn inspect_registered_configs() -> Vec<(i32, usize)> {
|
||||
let mut configs: Vec<(i32, usize)> = inventory::iter::<ConfigRecord>
|
||||
.into_iter()
|
||||
.map(|record| (record.priority, record.apply as usize))
|
||||
.collect();
|
||||
configs.sort_by_key(|(priority, _)| *priority);
|
||||
configs
|
||||
}
|
||||
|
||||
/// Returns the count of registered configuration records.
|
||||
pub fn registered_config_count() -> usize {
|
||||
inventory::iter::<ConfigRecord>.into_iter().count()
|
||||
}
|
||||
@@ -95,10 +95,10 @@ async fn api_client_retry() -> Result<(), Box<dyn std::error::Error>> {
|
||||
"http://example.com/".parse()?,
|
||||
])
|
||||
.with_retries(3)
|
||||
.build::<HttpClientError>()?;
|
||||
.build()?;
|
||||
|
||||
let req = client.create_get_request(&["/"], NO_PARAMS);
|
||||
let resp = client.send::<HttpClientError>(req).await?;
|
||||
let req = client.create_get_request(&["/"], NO_PARAMS).unwrap();
|
||||
let resp = client.send(req).await?;
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
@@ -111,10 +111,7 @@ async fn api_client_retry() -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[test]
|
||||
fn host_updating() {
|
||||
let url = Url::new("http://example.com", None).unwrap();
|
||||
let mut client = ClientBuilder::new::<_, &str>(url)
|
||||
.unwrap()
|
||||
.build::<&str>()
|
||||
.unwrap();
|
||||
let mut client = ClientBuilder::new(url).unwrap().build().unwrap();
|
||||
|
||||
// check that the url is set correctly
|
||||
let current_url = client.current_url();
|
||||
@@ -171,10 +168,10 @@ fn host_updating() {
|
||||
#[cfg(feature = "tunneling")]
|
||||
fn fronted_host_updating() {
|
||||
let url = Url::new("http://example.com", Some(vec!["http://front1.com"])).unwrap();
|
||||
let mut client = ClientBuilder::new::<_, &str>(url)
|
||||
let mut client = ClientBuilder::new(url)
|
||||
.unwrap()
|
||||
.with_fronting(crate::fronted::FrontPolicy::Always)
|
||||
.build::<&str>()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// check that the url is set correctly
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
use nym_http_api_client::registry;
|
||||
|
||||
// Create separate modules to avoid name conflicts
|
||||
mod config_early {
|
||||
use nym_http_api_client_macro::client_defaults;
|
||||
|
||||
client_defaults!(
|
||||
priority = -200;
|
||||
tcp_nodelay = true
|
||||
);
|
||||
}
|
||||
|
||||
mod config_late {
|
||||
use nym_http_api_client_macro::client_defaults;
|
||||
|
||||
client_defaults!(
|
||||
priority = 100;
|
||||
pool_idle_timeout = std::time::Duration::from_secs(90)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_registry_collects_configs() {
|
||||
// Verify that configurations are being registered
|
||||
let count = registry::registered_config_count();
|
||||
// Should have at least the ones we registered above plus the default from lib.rs
|
||||
assert!(
|
||||
count >= 3,
|
||||
"Expected at least 3 registered configs, got {}",
|
||||
count
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_builder_applies_configs() {
|
||||
// Test that default_builder returns a configured builder
|
||||
let _builder = registry::default_builder();
|
||||
// The builder should have all configurations applied
|
||||
// We can't easily inspect the internals, but we verify it doesn't panic
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_client_works() {
|
||||
// Test that we can successfully build a client with all configurations
|
||||
let result = registry::build_client();
|
||||
assert!(result.is_ok(), "Failed to build client: {:?}", result.err());
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[test]
|
||||
fn test_inspect_configs() {
|
||||
// In debug mode, test that we can inspect registered configurations
|
||||
let configs = registry::inspect_registered_configs();
|
||||
|
||||
// Verify configs are sorted by priority
|
||||
for window in configs.windows(2) {
|
||||
assert!(window[0].0 <= window[1].0, "Configs not sorted by priority");
|
||||
}
|
||||
|
||||
// Verify we have configs at different priority levels
|
||||
let priorities: Vec<i32> = configs.iter().map(|(p, _)| *p).collect();
|
||||
assert!(
|
||||
priorities.iter().any(|&p| p < 0),
|
||||
"Expected negative priority configs"
|
||||
);
|
||||
assert!(
|
||||
priorities.iter().any(|&p| p >= 0),
|
||||
"Expected non-negative priority configs"
|
||||
);
|
||||
}
|
||||
@@ -55,6 +55,7 @@ pub struct ApiUrl {
|
||||
pub front_hosts: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ApiUrlConst<'a> {
|
||||
pub url: &'a str,
|
||||
pub front_hosts: Option<&'a [&'a str]>,
|
||||
@@ -188,8 +189,14 @@ impl NymNetworkDetails {
|
||||
),
|
||||
},
|
||||
nym_vpn_api_url: parse_optional_str(mainnet::NYM_VPN_API),
|
||||
nym_api_urls: None,
|
||||
nym_vpn_api_urls: None,
|
||||
nym_api_urls: Some(mainnet::NYM_APIS.iter().copied().map(Into::into).collect()),
|
||||
nym_vpn_api_urls: Some(
|
||||
mainnet::NYM_VPN_APIS
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,3 +25,5 @@ url = { workspace = true }
|
||||
nym-crypto = { path = "../crypto", features = ["asymmetric"] }
|
||||
nym-task = { path = "../task" }
|
||||
nym-validator-client = { path = "../client-libs/validator-client" }
|
||||
nym-http-api-client = { path = "../http-api-client" }
|
||||
nym-api-requests = { path = "../../nym-api/nym-api-requests" }
|
||||
|
||||
@@ -10,7 +10,7 @@ use futures::StreamExt;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_task::ShutdownToken;
|
||||
use nym_validator_client::models::NymNodeDescription;
|
||||
use nym_validator_client::NymApiClient;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::net::SocketAddr;
|
||||
@@ -135,10 +135,15 @@ impl VerlocMeasurer {
|
||||
let mut api_endpoints = self.config.nym_api_urls.clone();
|
||||
api_endpoints.shuffle(&mut thread_rng());
|
||||
for api_endpoint in api_endpoints {
|
||||
let client = NymApiClient::new_with_user_agent(
|
||||
api_endpoint.clone(),
|
||||
self.config.user_agent.clone(),
|
||||
);
|
||||
let client = match nym_http_api_client::Client::builder(api_endpoint.clone())
|
||||
.and_then(|b| b.with_user_agent(self.config.user_agent.clone()).build())
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(err) => {
|
||||
warn!("failed to create client for {api_endpoint}: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match client.get_all_described_nodes().await {
|
||||
Ok(res) => return Some(res),
|
||||
Err(err) => {
|
||||
|
||||
@@ -34,6 +34,7 @@ nym-statistics-common = { path = "../../statistics" }
|
||||
nym-task = { path = "../../task" }
|
||||
nym-topology = { path = "../../topology", features = ["wasm-serde-types"] }
|
||||
nym-validator-client = { path = "../../client-libs/validator-client", default-features = false }
|
||||
nym-http-api-client = { path = "../../http-api-client" }
|
||||
wasm-utils = { path = "../utils" }
|
||||
wasm-storage = { path = "../storage" }
|
||||
|
||||
|
||||
@@ -37,6 +37,12 @@ pub enum WasmCoreError {
|
||||
source: ValidatorClientError,
|
||||
},
|
||||
|
||||
#[error("failed to query nym api: {source}")]
|
||||
NymApiQueryError {
|
||||
#[from]
|
||||
source: nym_validator_client::nym_api::error::NymAPIError,
|
||||
},
|
||||
|
||||
#[error("The provided wasm topology was invalid: {source}")]
|
||||
WasmTopologyError {
|
||||
#[from]
|
||||
|
||||
@@ -19,9 +19,9 @@ use nym_client_core::init::{
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag;
|
||||
use nym_topology::wasm_helpers::WasmFriendlyNymTopology;
|
||||
use nym_topology::{NymTopology, RoutingNode};
|
||||
use nym_topology::{EpochRewardedSet, NymTopology, RoutingNode};
|
||||
use nym_validator_client::client::IdentityKey;
|
||||
use nym_validator_client::{NymApiClient, UserAgent};
|
||||
use nym_validator_client::{nym_api::NymApiClientExt, UserAgent};
|
||||
use rand::thread_rng;
|
||||
use url::Url;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
@@ -72,7 +72,16 @@ pub async fn current_network_topology_async(
|
||||
}
|
||||
};
|
||||
|
||||
let api_client = NymApiClient::new(url);
|
||||
let api_client = nym_http_api_client::Client::builder(url.clone())
|
||||
.map_err(|_err| WasmCoreError::MalformedUrl {
|
||||
raw: nym_api_url.to_string(),
|
||||
source: url::ParseError::EmptyHost,
|
||||
})?
|
||||
.build()
|
||||
.map_err(|_err| WasmCoreError::MalformedUrl {
|
||||
raw: nym_api_url.to_string(),
|
||||
source: url::ParseError::EmptyHost,
|
||||
})?;
|
||||
let rewarded_set = api_client.get_current_rewarded_set().await?;
|
||||
let mixnodes_res = api_client
|
||||
.get_all_basic_active_mixing_assigned_nodes_with_metadata()
|
||||
@@ -90,9 +99,14 @@ pub async fn current_network_topology_async(
|
||||
|
||||
let gateways = gateways_res.nodes;
|
||||
|
||||
let topology = NymTopology::new(metadata.to_topology_metadata(), rewarded_set, Vec::new())
|
||||
.with_skimmed_nodes(&mixnodes)
|
||||
.with_skimmed_nodes(&gateways);
|
||||
let epoch_rewarded_set: EpochRewardedSet = rewarded_set.into();
|
||||
let topology = NymTopology::new(
|
||||
metadata.to_topology_metadata(),
|
||||
epoch_rewarded_set,
|
||||
Vec::new(),
|
||||
)
|
||||
.with_skimmed_nodes(&mixnodes)
|
||||
.with_skimmed_nodes(&gateways);
|
||||
|
||||
Ok(topology.into())
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ pub use nym_client_core::{
|
||||
pub use nym_gateway_client::{
|
||||
error::GatewayClientError, GatewayClient, GatewayClientConfig, GatewayConfig,
|
||||
};
|
||||
pub use nym_http_api_client::Client as ApiClient;
|
||||
pub use nym_sphinx::{
|
||||
addressing::{clients::Recipient, nodes::NodeIdentity},
|
||||
params::PacketType,
|
||||
@@ -29,7 +30,6 @@ pub use nym_sphinx::{
|
||||
pub use nym_statistics_common::clients::ClientStatsSender;
|
||||
pub use nym_task;
|
||||
pub use nym_topology::{HardcodedTopologyProvider, MixLayer, NymTopology, TopologyProvider};
|
||||
pub use nym_validator_client::nym_api::Client as ApiClient;
|
||||
pub use nym_validator_client::{DirectSigningReqwestRpcNyxdClient, QueryReqwestRpcNyxdClient};
|
||||
// TODO: that's a very nasty import path. it should come from contracts instead!
|
||||
pub use nym_validator_client::client::IdentityKey;
|
||||
|
||||
@@ -7,16 +7,14 @@ use tracing::instrument;
|
||||
use nym_http_api_client::{ApiClient, Client, HttpClientError, NO_PARAMS};
|
||||
|
||||
use nym_wireguard_private_metadata_shared::{
|
||||
routes, Version, {ErrorResponse, Request, Response},
|
||||
routes, Version, {Request, Response},
|
||||
};
|
||||
|
||||
pub type WireguardMetadataApiClientError = HttpClientError<ErrorResponse>;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
pub trait WireguardMetadataApiClient: ApiClient {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
async fn version(&self) -> Result<Version, WireguardMetadataApiClientError> {
|
||||
async fn version(&self) -> Result<Version, HttpClientError> {
|
||||
let version: u64 = self
|
||||
.get_json(
|
||||
&[routes::V1_API_VERSION, routes::BANDWIDTH, routes::VERSION],
|
||||
@@ -30,7 +28,7 @@ pub trait WireguardMetadataApiClient: ApiClient {
|
||||
async fn available_bandwidth(
|
||||
&self,
|
||||
request_body: &Request,
|
||||
) -> Result<Response, WireguardMetadataApiClientError> {
|
||||
) -> Result<Response, HttpClientError> {
|
||||
self.post_json(
|
||||
&[routes::V1_API_VERSION, routes::BANDWIDTH, routes::AVAILABLE],
|
||||
NO_PARAMS,
|
||||
@@ -40,10 +38,7 @@ pub trait WireguardMetadataApiClient: ApiClient {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, request_body))]
|
||||
async fn topup_bandwidth(
|
||||
&self,
|
||||
request_body: &Request,
|
||||
) -> Result<Response, WireguardMetadataApiClientError> {
|
||||
async fn topup_bandwidth(&self, request_body: &Request) -> Result<Response, HttpClientError> {
|
||||
self.post_json(
|
||||
&[routes::V1_API_VERSION, routes::BANDWIDTH, routes::TOPUP],
|
||||
NO_PARAMS,
|
||||
|
||||
@@ -13,7 +13,7 @@ mod tests {
|
||||
use nym_wireguard_private_metadata_server::{
|
||||
AppState, PeerControllerTransceiver, RouterBuilder,
|
||||
};
|
||||
use nym_wireguard_private_metadata_shared::{latest, v0, v1, ErrorResponse};
|
||||
use nym_wireguard_private_metadata_shared::{latest, v0, v1};
|
||||
use tokio::{net::TcpListener, sync::mpsc};
|
||||
|
||||
pub(crate) const VERIFIER_AVAILABLE_BANDWIDTH: i64 = 42;
|
||||
@@ -140,7 +140,7 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
Client::new_url::<_, ErrorResponse>(addr.to_string(), None).unwrap()
|
||||
Client::new_url(addr.to_string(), None).unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -15,7 +15,6 @@ pub(crate) mod test {
|
||||
use nym_http_api_common::{FormattedResponse, OutputParams};
|
||||
use nym_wireguard::{peer_controller::PeerControlRequest, CONTROL_CHANNEL_SIZE};
|
||||
use nym_wireguard_private_metadata_server::PeerControllerTransceiver;
|
||||
use nym_wireguard_private_metadata_shared::ErrorResponse;
|
||||
use nym_wireguard_private_metadata_shared::{
|
||||
v0 as latest, AxumErrorResponse, AxumResult, Construct, Extract, Request, Response,
|
||||
};
|
||||
@@ -141,6 +140,6 @@ pub(crate) mod test {
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
Client::new_url::<_, ErrorResponse>(addr.to_string(), None).unwrap()
|
||||
Client::new_url(addr.to_string(), None).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -744,7 +744,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"cosmwasm-std",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -52,7 +52,7 @@ impl TestSetup {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_ctx(&self) -> QueryCtx {
|
||||
pub fn query_ctx(&self) -> QueryCtx<'_> {
|
||||
QueryCtx::from((self.deps.as_ref(), self.env.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,13 +73,13 @@ impl TestSetupSimple {
|
||||
message_info(&admin, &[])
|
||||
}
|
||||
|
||||
pub fn execute_ctx(&mut self, sender: MessageInfo) -> ExecCtx {
|
||||
pub fn execute_ctx(&mut self, sender: MessageInfo) -> ExecCtx<'_> {
|
||||
let env = self.env.clone();
|
||||
ExecCtx::from((self.deps.as_mut(), env, sender))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn query_ctx(&self) -> QueryCtx {
|
||||
pub fn query_ctx(&self) -> QueryCtx<'_> {
|
||||
QueryCtx::from((self.deps.as_ref(), self.env.clone()))
|
||||
}
|
||||
|
||||
|
||||
@@ -139,9 +139,9 @@ mod tests {
|
||||
|
||||
fn add_dummy_mixes_with_delegations(test: &mut TestSetup, delegators: usize, mixes: usize) {
|
||||
for i in 0..mixes {
|
||||
let mix_id = test.add_legacy_mixnode(&test.make_addr(format!("mix-owner{}", i)), None);
|
||||
let mix_id = test.add_legacy_mixnode(&test.make_addr(format!("mix-owner{i}")), None);
|
||||
for delegator in 0..delegators {
|
||||
let name = &test.make_addr(format!("delegator{}", delegator));
|
||||
let name = &test.make_addr(format!("delegator{delegator}"));
|
||||
test.add_immediate_delegation(name, 100_000_000u32, mix_id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ mod tests {
|
||||
|
||||
let amount1 = coin(100_000_000, TEST_COIN_DENOM);
|
||||
|
||||
let sender1 = message_info(owner, &[amount1.clone()]);
|
||||
let sender1 = message_info(owner, std::slice::from_ref(&amount1));
|
||||
|
||||
try_delegate_to_node(test.deps_mut(), env.clone(), sender1, mix_id).unwrap();
|
||||
|
||||
|
||||
@@ -503,8 +503,8 @@ pub(crate) mod tests {
|
||||
storage,
|
||||
id,
|
||||
&UnbondedMixnode {
|
||||
identity_key: format!("dummy{}", id),
|
||||
owner: Addr::unchecked(format!("dummy{}", id)),
|
||||
identity_key: format!("dummy{id}"),
|
||||
owner: Addr::unchecked(format!("dummy{id}")),
|
||||
proxy: None,
|
||||
unbonding_height: 123,
|
||||
},
|
||||
@@ -570,7 +570,7 @@ pub(crate) mod tests {
|
||||
storage,
|
||||
id,
|
||||
&UnbondedMixnode {
|
||||
identity_key: format!("dummy{}", id),
|
||||
identity_key: format!("dummy{id}"),
|
||||
owner: owner.clone(),
|
||||
proxy: None,
|
||||
unbonding_height: 123,
|
||||
@@ -817,7 +817,7 @@ pub(crate) mod tests {
|
||||
id,
|
||||
&UnbondedMixnode {
|
||||
identity_key: identity.to_string(),
|
||||
owner: Addr::unchecked(format!("dummy{}", id)),
|
||||
owner: Addr::unchecked(format!("dummy{id}")),
|
||||
proxy: None,
|
||||
unbonding_height: 123,
|
||||
},
|
||||
|
||||
@@ -165,9 +165,9 @@ pub mod test_helpers {
|
||||
#[track_caller]
|
||||
pub fn assert_eq_with_leeway(a: Uint128, b: Uint128, leeway: Uint128) {
|
||||
if a > b {
|
||||
assert!(a - b <= leeway, "{} != {}", a, b)
|
||||
assert!(a - b <= leeway, "{a} != {b}")
|
||||
} else {
|
||||
assert!(b - a <= leeway, "{} != {}", a, b)
|
||||
assert!(b - a <= leeway, "{a} != {b}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,9 +175,9 @@ pub mod test_helpers {
|
||||
pub fn assert_decimals(a: Decimal, b: Decimal) {
|
||||
let epsilon = Decimal::from_ratio(1u128, 100_000_000u128);
|
||||
if a > b {
|
||||
assert!(a - b < epsilon, "{} != {}", a, b)
|
||||
assert!(a - b < epsilon, "{a} != {b}")
|
||||
} else {
|
||||
assert!(b - a < epsilon, "{} != {}", a, b)
|
||||
assert!(b - a < epsilon, "{a} != {b}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1699,7 +1699,7 @@ pub mod test_helpers {
|
||||
deps.branch(),
|
||||
&env,
|
||||
env.block.height,
|
||||
Addr::unchecked(format!("owner{}", i)),
|
||||
Addr::unchecked(format!("owner{i}")),
|
||||
mix_id,
|
||||
tests::fixtures::good_mixnode_pledge().pop().unwrap(),
|
||||
)
|
||||
@@ -1713,7 +1713,7 @@ pub mod test_helpers {
|
||||
n: usize,
|
||||
) {
|
||||
for i in 0..n {
|
||||
add_unbonded_mixnode(&mut rng, deps.branch(), None, &addr(format!("owner{}", i)));
|
||||
add_unbonded_mixnode(&mut rng, deps.branch(), None, &addr(format!("owner{i}")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,7 +1765,7 @@ pub mod test_helpers {
|
||||
id,
|
||||
&UnbondedMixnode {
|
||||
identity_key: identity_key
|
||||
.unwrap_or(&*format!("identity{}", id))
|
||||
.unwrap_or(&*format!("identity{id}"))
|
||||
.to_string(),
|
||||
owner: Addr::unchecked(owner),
|
||||
proxy: None,
|
||||
|
||||
@@ -131,7 +131,7 @@ impl PreInitContract {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn deps(&self) -> Deps {
|
||||
pub(crate) fn deps(&self) -> Deps<'_> {
|
||||
Deps {
|
||||
storage: &self.storage,
|
||||
api: &self.api,
|
||||
@@ -139,7 +139,7 @@ impl PreInitContract {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn deps_mut(&mut self) -> DepsMut {
|
||||
pub(crate) fn deps_mut(&mut self) -> DepsMut<'_> {
|
||||
DepsMut {
|
||||
storage: &mut self.storage,
|
||||
api: &self.api,
|
||||
@@ -147,7 +147,7 @@ impl PreInitContract {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn querier(&self) -> QuerierWrapper {
|
||||
pub(crate) fn querier(&self) -> QuerierWrapper<'_> {
|
||||
self.tester_builder.querier()
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ mod tests {
|
||||
let response = execute(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
message_info(&admin, &[amount.clone()]),
|
||||
message_info(&admin, std::slice::from_ref(&amount)),
|
||||
msg,
|
||||
);
|
||||
assert_eq!(
|
||||
|
||||
+8
-2
@@ -20,16 +20,22 @@ use nym_sdk::mixnet;
|
||||
use nym_sdk::mixnet::MixnetMessageSender;
|
||||
use nym_topology::provider_trait::{async_trait, TopologyProvider};
|
||||
use nym_topology::{nym_topology_from_detailed, NymTopology};
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use url::Url;
|
||||
|
||||
struct MyTopologyProvider {
|
||||
validator_client: nym_validator_client::client::NymApiClient,
|
||||
validator_client: nym_http_api_client::Client,
|
||||
}
|
||||
|
||||
impl MyTopologyProvider {
|
||||
fn new(nym_api_url: Url) -> MyTopologyProvider {
|
||||
let validator_client = nym_http_api_client::Client::builder::<_, nym_validator_client::models::RequestError>(nym_api_url)
|
||||
.expect("Failed to create API client builder")
|
||||
.build::<nym_validator_client::models::RequestError>()
|
||||
.expect("Failed to build API client");
|
||||
|
||||
MyTopologyProvider {
|
||||
validator_client: nym_validator_client::client::NymApiClient::new(nym_api_url),
|
||||
validator_client,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ nym-task = { path = "../common/task" }
|
||||
nym-topology = { path = "../common/topology" }
|
||||
nym-api-requests = { path = "nym-api-requests" }
|
||||
nym-validator-client = { path = "../common/client-libs/validator-client" }
|
||||
nym-http-api-client = { path = "../common/http-api-client" }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["output_format", "openapi", "basic_tracing"] }
|
||||
nym-node-tester-utils = { path = "../common/node-tester-utils" }
|
||||
nym-node-requests = { path = "../nym-node/nym-node-requests" }
|
||||
|
||||
@@ -8,7 +8,9 @@ use nym_crypto::asymmetric::x25519::serde_helpers::bs58_x25519_pubkey;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_mixnet_contract_common::reward_params::Performance;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_network_defaults::{DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT};
|
||||
use nym_network_defaults::{
|
||||
DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT, WG_METADATA_PORT, WG_TUNNEL_PORT,
|
||||
};
|
||||
use nym_node_requests::api::v1::authenticator::models::Authenticator;
|
||||
use nym_node_requests::api::v1::gateway::models::Wireguard;
|
||||
use nym_node_requests::api::v1::ip_packet_router::models::IpPacketRouter;
|
||||
@@ -313,11 +315,20 @@ impl From<Authenticator> for AuthenticatorDetails {
|
||||
pub struct WireguardDetails {
|
||||
// NOTE: the port field is deprecated in favour of tunnel_port
|
||||
pub port: u16,
|
||||
#[serde(default = "default_tunnel_port")]
|
||||
pub tunnel_port: u16,
|
||||
#[serde(default = "default_metadata_port")]
|
||||
pub metadata_port: u16,
|
||||
pub public_key: String,
|
||||
}
|
||||
|
||||
fn default_tunnel_port() -> u16 {
|
||||
WG_TUNNEL_PORT
|
||||
}
|
||||
fn default_metadata_port() -> u16 {
|
||||
WG_METADATA_PORT
|
||||
}
|
||||
|
||||
// works for current simple case.
|
||||
impl From<Wireguard> for WireguardDetails {
|
||||
fn from(value: Wireguard) -> Self {
|
||||
|
||||
@@ -13,6 +13,7 @@ use nym_dkg::Threshold;
|
||||
use nym_ecash_contract_common::deposit::DepositId;
|
||||
use nym_ecash_contract_common::redeem_credential::BATCH_REDEMPTION_PROPOSAL_TITLE;
|
||||
use nym_validator_client::coconut::EcashApiError;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use thiserror::Error;
|
||||
@@ -46,6 +47,9 @@ pub enum EcashError {
|
||||
#[error("coconut api query failure: {0}")]
|
||||
CoconutApiError(#[from] EcashApiError),
|
||||
|
||||
#[error("nym api query failure: {0}")]
|
||||
NymApiError(#[from] NymAPIError),
|
||||
|
||||
#[error(transparent)]
|
||||
SerdeJsonError(#[from] serde_json::Error),
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ use nym_ecash_contract_common::redeem_credential::BATCH_REDEMPTION_PROPOSAL_TITL
|
||||
use nym_ecash_time::{ecash_default_expiration_date, ecash_today_date};
|
||||
use nym_task::TaskClient;
|
||||
use nym_ticketbooks_merkle::{IssuedTicketbook, IssuedTicketbooksFullMerkleProof, MerkleLeaf};
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use nym_validator_client::EcashApiClient;
|
||||
use rand::{thread_rng, RngCore};
|
||||
|
||||
@@ -67,7 +67,7 @@ use nym_validator_client::nym_api::routes::{
|
||||
use nym_validator_client::nyxd::cosmwasm_client::logs::Log;
|
||||
use nym_validator_client::nyxd::cosmwasm_client::types::ExecuteResult;
|
||||
use nym_validator_client::nyxd::{AccountId, ExecTxResult, Fee, Hash, TxResponse};
|
||||
use nym_validator_client::{EcashApiClient, NymApiClient};
|
||||
use nym_validator_client::EcashApiClient;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
@@ -1148,7 +1148,10 @@ impl DummyCommunicationChannel {
|
||||
cosmos_address: AccountId,
|
||||
) -> Self {
|
||||
let client = EcashApiClient {
|
||||
api_client: NymApiClient::new("http://localhost:1234".parse().unwrap()),
|
||||
api_client: nym_http_api_client::Client::new(
|
||||
"http://localhost:1234".parse().unwrap(),
|
||||
None,
|
||||
),
|
||||
verification_key: aggregated_verification_key,
|
||||
node_id: 1,
|
||||
cosmos_address,
|
||||
|
||||
@@ -26,7 +26,10 @@ pub fn new_client(
|
||||
base_url: impl IntoUrl,
|
||||
bearer_token: impl Into<String>,
|
||||
) -> Result<VpnApiClient, VpnApiClientError> {
|
||||
let url = base_url.into_url()?;
|
||||
let raw = base_url.as_str().to_string();
|
||||
let url = base_url
|
||||
.into_url()
|
||||
.map_err(|source| VpnApiClientError::MalformedUrl { raw, source })?;
|
||||
Ok(VpnApiClient {
|
||||
inner: Client::builder(url)?
|
||||
.with_user_agent(format!(
|
||||
@@ -97,9 +100,14 @@ impl NymVpnApiClient for VpnApiClient {
|
||||
{
|
||||
let req = self
|
||||
.inner
|
||||
.create_get_request(path, NO_PARAMS)
|
||||
.create_get_request(path, NO_PARAMS)?
|
||||
.bearer_auth(&self.bearer_token)
|
||||
.send();
|
||||
.build()
|
||||
.map_err(VpnApiClientError::reqwest_client_build_error)?;
|
||||
|
||||
let url = req.url().clone();
|
||||
|
||||
let req = reqwest::Client::new().execute(req);
|
||||
|
||||
// the only reason for that target lock is so that I could call this method from an ephemeral test
|
||||
// running in non-wasm mode (since I wanted to use tokio)
|
||||
@@ -110,8 +118,9 @@ impl NymVpnApiClient for VpnApiClient {
|
||||
.map_err(|_timeout| HttpClientError::RequestTimeout)??;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let res = req.await?;
|
||||
|
||||
let res = req
|
||||
.await
|
||||
.map_err(|source| VpnApiClientError::request_send_error(url, source))?;
|
||||
parse_response(res, false).await
|
||||
}
|
||||
|
||||
@@ -129,9 +138,14 @@ impl NymVpnApiClient for VpnApiClient {
|
||||
{
|
||||
let req = self
|
||||
.inner
|
||||
.create_post_request(path, params, json_body)
|
||||
.create_post_request(path, params, json_body)?
|
||||
.bearer_auth(&self.bearer_token)
|
||||
.send();
|
||||
.build()
|
||||
.map_err(VpnApiClientError::reqwest_client_build_error)?;
|
||||
|
||||
let url = req.url().clone();
|
||||
|
||||
let req = reqwest::Client::new().execute(req);
|
||||
|
||||
// the only reason for that target lock is so that I could call this method from an ephemeral test
|
||||
// running in non-wasm mode (since I wanted to use tokio)
|
||||
@@ -142,7 +156,9 @@ impl NymVpnApiClient for VpnApiClient {
|
||||
.map_err(|_timeout| HttpClientError::RequestTimeout)??;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let res = req.await?;
|
||||
let res = req
|
||||
.await
|
||||
.map_err(|source| VpnApiClientError::request_send_error(url, source))?;
|
||||
|
||||
parse_response(res, false).await
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
||||
};
|
||||
use nym_credentials_interface::Base58;
|
||||
use nym_validator_client::ecash::BlindSignRequestBody;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
use nym_ecash_signer_check::SignerCheckError;
|
||||
use nym_validator_client::coconut::EcashApiError;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nym_api::{error::NymAPIError, EpochId};
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
@@ -71,6 +71,12 @@ pub enum CredentialProxyError {
|
||||
source: EcashApiError,
|
||||
},
|
||||
|
||||
#[error("Nym API request failed: {source}")]
|
||||
NymApiFailure {
|
||||
#[from]
|
||||
source: NymAPIError,
|
||||
},
|
||||
|
||||
#[error("Compact ecash internal error: {0}")]
|
||||
CompactEcashInternalError(#[from] nym_compact_ecash::error::CompactEcashError),
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ use nym_ecash_contract_common::deposit::DepositId;
|
||||
use nym_ecash_contract_common::msg::ExecuteMsg;
|
||||
use nym_validator_client::coconut::EcashApiError;
|
||||
use nym_validator_client::nym_api::EpochId;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::nyxd::contract_traits::dkg_query_client::Epoch;
|
||||
use nym_validator_client::nyxd::contract_traits::{
|
||||
DkgQueryClient, NymContractsProvider, PagedDkgQueryClient,
|
||||
|
||||
@@ -40,3 +40,5 @@ nym-sphinx = { path = "../common/nymsphinx" }
|
||||
nym-topology = { path = "../common/topology" }
|
||||
nym-types = { path = "../common/types" }
|
||||
nym-validator-client = { path = "../common/client-libs/validator-client" }
|
||||
nym-http-api-client = { path = "../common/http-api-client" }
|
||||
nym-mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
|
||||
@@ -6,12 +6,15 @@ use log::{info, warn};
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_client_core::config::ForgetMe;
|
||||
use nym_crypto::asymmetric::ed25519::PrivateKey;
|
||||
use nym_mixnet_contract_common::EpochRewardedSet;
|
||||
use nym_network_defaults::setup_env;
|
||||
use nym_network_defaults::var_names::NYM_API;
|
||||
use nym_sdk::mixnet::{self, MixnetClient};
|
||||
use nym_sphinx::chunking::monitoring;
|
||||
use nym_topology::provider_trait::ToTopologyMetadata;
|
||||
use nym_topology::{HardcodedTopologyProvider, NymTopology};
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::UserAgent;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::sync::LazyLock;
|
||||
@@ -160,10 +163,9 @@ async fn nym_topology_from_env() -> anyhow::Result<NymTopology> {
|
||||
let api_url = std::env::var(NYM_API)?;
|
||||
|
||||
info!("Generating topology from {api_url}");
|
||||
let client = nym_validator_client::client::NymApiClient::new_with_user_agent(
|
||||
api_url.parse()?,
|
||||
bin_info!(),
|
||||
);
|
||||
let client = nym_http_api_client::Client::builder(api_url)?
|
||||
.with_user_agent(UserAgent::from(bin_info!()))
|
||||
.build()?;
|
||||
|
||||
let rewarded_set = client.get_current_rewarded_set().await?;
|
||||
|
||||
@@ -172,10 +174,15 @@ async fn nym_topology_from_env() -> anyhow::Result<NymTopology> {
|
||||
let nodes = nodes_response.nodes;
|
||||
let metadata = nodes_response.metadata;
|
||||
|
||||
Ok(
|
||||
NymTopology::new(metadata.to_topology_metadata(), rewarded_set, Vec::new())
|
||||
.with_skimmed_nodes(&nodes),
|
||||
// Convert RewardedSetResponse to EpochRewardedSet which can then be converted to CachedEpochRewardedSet
|
||||
let epoch_rewarded_set: EpochRewardedSet = rewarded_set.into();
|
||||
|
||||
Ok(NymTopology::new(
|
||||
metadata.to_topology_metadata(),
|
||||
epoch_rewarded_set,
|
||||
Vec::new(),
|
||||
)
|
||||
.with_skimmed_nodes(&nodes))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
||||
@@ -5,11 +5,11 @@ use nym_node_requests::api::{client::NymNodeApiClientExt, v1::metrics::models::S
|
||||
use nym_validator_client::{
|
||||
client::{NodeId, NymNodeDetails},
|
||||
models::{DescribedNodeType, NymNodeDescription},
|
||||
NymApiClient,
|
||||
};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use nym_statistics_common::types::SessionType;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use std::collections::HashMap;
|
||||
use tokio::time::Duration;
|
||||
use tracing::instrument;
|
||||
@@ -60,13 +60,11 @@ async fn run(
|
||||
let nym_api = nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
|
||||
.no_hickory_dns()
|
||||
.with_timeout(nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
|
||||
let api_client = NymApiClient::from(nym_api);
|
||||
.build()?;
|
||||
|
||||
//SW TBC what nodes exactly need to be scraped, the skimmed node endpoint seems to return more nodes
|
||||
let bonded_nodes = api_client.get_all_bonded_nym_nodes().await?;
|
||||
let all_nodes = api_client.get_all_described_nodes().await?; //legacy node that did not upgrade the contract bond yet
|
||||
let bonded_nodes = nym_api.get_all_bonded_nym_nodes().await?;
|
||||
let all_nodes = nym_api.get_all_described_nodes().await?; //legacy node that did not upgrade the contract bond yet
|
||||
tracing::debug!("Fetched {} total nodes", all_nodes.len());
|
||||
|
||||
let mut nodes_to_scrape: HashMap<NodeId, MetricsScrapingData> = bonded_nodes
|
||||
|
||||
@@ -19,7 +19,7 @@ use nym_validator_client::{
|
||||
use nym_validator_client::{
|
||||
nym_nodes::{NodeRole, SkimmedNode},
|
||||
nyxd::{contract_traits::PagedMixnetQueryClient, AccountId},
|
||||
NymApiClient, QueryHttpRpcNyxdClient,
|
||||
QueryHttpRpcNyxdClient,
|
||||
};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
@@ -109,11 +109,9 @@ impl Monitor {
|
||||
nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
|
||||
.no_hickory_dns()
|
||||
.with_timeout(self.nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
.build()?;
|
||||
|
||||
let api_client = NymApiClient::from(nym_api);
|
||||
|
||||
let described_nodes = api_client
|
||||
let described_nodes = nym_api
|
||||
.get_all_described_nodes()
|
||||
.await
|
||||
.log_error("get_all_described_nodes")?
|
||||
@@ -135,7 +133,7 @@ impl Monitor {
|
||||
|
||||
tracing::info!("🟣 🚪 gateway nodes: {}", gateways.len());
|
||||
|
||||
let bonded_nym_nodes = api_client
|
||||
let bonded_nym_nodes = nym_api
|
||||
.get_all_bonded_nym_nodes()
|
||||
.await?
|
||||
.into_iter()
|
||||
@@ -146,10 +144,11 @@ impl Monitor {
|
||||
tracing::info!("🟣 bonded_nodes: {}", bonded_nym_nodes.len());
|
||||
|
||||
// returns only bonded nodes
|
||||
let nym_nodes = api_client
|
||||
.get_all_basic_nodes()
|
||||
let nym_nodes = nym_api
|
||||
.get_all_basic_nodes_with_metadata()
|
||||
.await
|
||||
.log_error("get_all_basic_nodes")?;
|
||||
.log_error("get_all_basic_nodes")?
|
||||
.nodes;
|
||||
|
||||
let nym_node_count = nym_nodes.len();
|
||||
tracing::info!("🟣 get_all_basic_nodes: {}", nym_node_count);
|
||||
@@ -167,8 +166,7 @@ impl Monitor {
|
||||
self.location_cached(node_description).await;
|
||||
}
|
||||
|
||||
let mixnodes_detailed = api_client
|
||||
.nym_api
|
||||
let mixnodes_detailed = nym_api
|
||||
.get_mixnodes_detailed_unfiltered()
|
||||
.await
|
||||
.log_error("get_mixnodes_detailed_unfiltered")?;
|
||||
@@ -190,15 +188,13 @@ impl Monitor {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mixnodes_described = api_client
|
||||
.nym_api
|
||||
let mixnodes_described = nym_api
|
||||
.get_mixnodes_described()
|
||||
.await
|
||||
.log_error("get_mixnodes_described")?;
|
||||
|
||||
tracing::info!("🟣 mixnodes_described: {}", mixnodes_described.len());
|
||||
let mixing_assigned_nodes = api_client
|
||||
.nym_api
|
||||
let mixing_assigned_nodes = nym_api
|
||||
.get_basic_active_mixing_assigned_nodes(false, None, None, false)
|
||||
.await
|
||||
.log_error("get_basic_active_mixing_assigned_nodes")?
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::api::v1::gateway::models::WebSockets;
|
||||
use crate::api::v1::node::models::{
|
||||
AuxiliaryDetails, NodeDescription, NodeRoles, SignedHostInformation,
|
||||
};
|
||||
use crate::api::ErrorResponse;
|
||||
use crate::routes;
|
||||
use async_trait::async_trait;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
@@ -21,7 +20,7 @@ use crate::api::v1::network_requester::models::NetworkRequester;
|
||||
use crate::api::v1::node_load::models::NodeLoad;
|
||||
pub use nym_http_api_client::Client;
|
||||
|
||||
pub type NymNodeApiClientError = HttpClientError<ErrorResponse>;
|
||||
pub type NymNodeApiClientError = HttpClientError;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
|
||||
@@ -10,7 +10,6 @@ use nym_task::ShutdownToken;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::models::{KeyRotationInfoResponse, NodeRefreshBody};
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
use nym_validator_client::NymApiClient;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::sync::Arc;
|
||||
@@ -27,7 +26,7 @@ pub struct NymApisClient {
|
||||
|
||||
struct InnerClient {
|
||||
// NOTE: this was implemented before the internal http client supported multiple URLs
|
||||
active_client: NymApiClient,
|
||||
active_client: Client,
|
||||
available_urls: Vec<Url>,
|
||||
shutdown_token: ShutdownToken,
|
||||
currently_used_api: usize,
|
||||
@@ -45,7 +44,7 @@ impl NymApisClient {
|
||||
let mut urls = nym_apis.to_vec();
|
||||
urls.shuffle(&mut thread_rng());
|
||||
|
||||
let active_client = nym_http_api_client::Client::builder(urls[0].clone())?
|
||||
let active_client = Client::builder(urls[0].clone())?
|
||||
.no_hickory_dns()
|
||||
.with_user_agent(NymNode::user_agent())
|
||||
.with_timeout(Duration::from_secs(5))
|
||||
@@ -53,7 +52,7 @@ impl NymApisClient {
|
||||
|
||||
Ok(NymApisClient {
|
||||
inner: Arc::new(RwLock::new(InnerClient {
|
||||
active_client: NymApiClient::from(active_client),
|
||||
active_client: active_client.clone(),
|
||||
available_urls: urls,
|
||||
shutdown_token,
|
||||
currently_used_api: 0,
|
||||
@@ -88,9 +87,19 @@ impl NymApisClient {
|
||||
if guard.currently_used_api != last_working_endpoint {
|
||||
drop(guard);
|
||||
let mut guard = self.inner.write().await;
|
||||
let next_url = guard.available_urls[last_working_endpoint].clone();
|
||||
guard.currently_used_api = last_working_endpoint;
|
||||
guard.active_client.change_nym_api(next_url);
|
||||
|
||||
// Provide all URLs starting from the working endpoint for automatic failover
|
||||
let rotated_urls: Vec<_> = guard
|
||||
.available_urls
|
||||
.iter()
|
||||
.cycle()
|
||||
.skip(last_working_endpoint)
|
||||
.take(guard.available_urls.len())
|
||||
.map(|u| u.clone().into())
|
||||
.collect();
|
||||
|
||||
guard.active_client.change_base_urls(rotated_urls);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
@@ -123,10 +132,10 @@ impl InnerClient {
|
||||
{
|
||||
let broadcast_fut =
|
||||
stream::iter(self.available_urls.clone()).for_each_concurrent(None, |url| {
|
||||
let nym_api = self
|
||||
.active_client
|
||||
.nym_api
|
||||
.clone_with_new_url(url.clone().into());
|
||||
let mut nym_api = self.active_client.clone();
|
||||
// For broadcast, we intentionally set a single URL per client
|
||||
// to ensure each endpoint receives the request
|
||||
nym_api.change_base_urls(vec![url.clone().into()]);
|
||||
let req_fut = req(nym_api, request_body);
|
||||
async move {
|
||||
if let Err(err) = req_fut.await {
|
||||
@@ -172,10 +181,10 @@ impl InnerClient {
|
||||
.skip(last_working)
|
||||
.chain(self.available_urls.iter().enumerate().take(last_working))
|
||||
{
|
||||
let nym_api = self
|
||||
.active_client
|
||||
.nym_api
|
||||
.clone_with_new_url(url.clone().into());
|
||||
let mut nym_api = self.active_client.clone();
|
||||
// For exhaustive query, we test each endpoint individually in sequence
|
||||
// to find a working one - so single URL is correct here
|
||||
nym_api.change_base_urls(vec![url.clone().into()]);
|
||||
|
||||
let timeout_fut = sleep(timeout_duration);
|
||||
let query_fut = req(nym_api);
|
||||
@@ -216,8 +225,8 @@ impl InnerClient {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<NymApiClient> for InnerClient {
|
||||
fn as_ref(&self) -> &NymApiClient {
|
||||
impl AsRef<Client> for InnerClient {
|
||||
fn as_ref(&self) -> &Client {
|
||||
&self.active_client
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::node::routing_filter::network_filter::NetworkRoutingFilter;
|
||||
use async_trait::async_trait;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_gateway::node::UserAgent;
|
||||
use nym_http_api_client::Client;
|
||||
use nym_node_metrics::prometheus_wrapper::{PrometheusMetric, PROMETHEUS_METRICS};
|
||||
use nym_noise::config::NoiseNetworkView;
|
||||
use nym_task::ShutdownToken;
|
||||
@@ -20,7 +21,7 @@ use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::nym_nodes::{
|
||||
NodesByAddressesResponse, SemiSkimmedNode, SemiSkimmedNodesWithMetadata,
|
||||
};
|
||||
use nym_validator_client::{NymApiClient, ValidatorClientError};
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::ops::Deref;
|
||||
@@ -35,7 +36,7 @@ use url::Url;
|
||||
const LOCAL_NODE_ID: NodeId = 1234567890;
|
||||
|
||||
struct NodesQuerier {
|
||||
client: NymApiClient,
|
||||
client: Client,
|
||||
nym_api_urls: Vec<Url>,
|
||||
currently_used_api: usize,
|
||||
}
|
||||
@@ -49,7 +50,7 @@ impl NodesQuerier {
|
||||
|
||||
self.currently_used_api = (self.currently_used_api + 1) % self.nym_api_urls.len();
|
||||
self.client
|
||||
.change_nym_api(self.nym_api_urls[self.currently_used_api].clone())
|
||||
.change_base_urls(self.nym_api_urls.iter().map(|u| u.clone().into()).collect())
|
||||
}
|
||||
|
||||
async fn rewarded_set(&mut self) -> Result<EpochRewardedSet, ValidatorClientError> {
|
||||
@@ -62,7 +63,7 @@ impl NodesQuerier {
|
||||
if res.is_err() {
|
||||
self.use_next_nym_api()
|
||||
}
|
||||
res
|
||||
Ok(res?.into())
|
||||
}
|
||||
|
||||
async fn current_nymnodes(
|
||||
@@ -77,7 +78,7 @@ impl NodesQuerier {
|
||||
if res.is_err() {
|
||||
self.use_next_nym_api()
|
||||
}
|
||||
res
|
||||
Ok(res?)
|
||||
}
|
||||
|
||||
async fn query_for_info(
|
||||
@@ -86,7 +87,6 @@ impl NodesQuerier {
|
||||
) -> Result<NodesByAddressesResponse, ValidatorClientError> {
|
||||
let res = self
|
||||
.client
|
||||
.nym_api
|
||||
.nodes_by_addresses(ips)
|
||||
.await
|
||||
.inspect_err(|err| error!("failed to obtain node information: {err}"));
|
||||
@@ -228,7 +228,7 @@ impl NetworkRefresher {
|
||||
|
||||
let mut this = NetworkRefresher {
|
||||
querier: NodesQuerier {
|
||||
client: NymApiClient::from(nym_api),
|
||||
client: nym_api,
|
||||
nym_api_urls,
|
||||
currently_used_api: 0,
|
||||
},
|
||||
|
||||
@@ -6,7 +6,6 @@ use nym_task::ShutdownToken;
|
||||
|
||||
use celes::Country;
|
||||
use nym_validator_client::models::NymNodeDescription;
|
||||
use nym_validator_client::NymApiClient;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use std::{net::IpAddr, sync::Arc};
|
||||
@@ -14,6 +13,8 @@ use tokio::sync::RwLock;
|
||||
use tokio::time::interval;
|
||||
use url::Url;
|
||||
|
||||
use nym_http_api_client::Client;
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use tracing::{error, info, trace, warn};
|
||||
|
||||
const NETWORK_CACHE_TTL: Duration = Duration::from_secs(600);
|
||||
@@ -22,7 +23,7 @@ type IpToCountryMap = HashMap<IpAddr, Option<Country>>;
|
||||
|
||||
// SW this should use a proper NS API client once it exists
|
||||
struct NodesQuerier {
|
||||
client: NymApiClient,
|
||||
client: Client,
|
||||
}
|
||||
|
||||
impl NodesQuerier {
|
||||
@@ -99,14 +100,11 @@ impl NetworkRefresher {
|
||||
this
|
||||
}
|
||||
|
||||
fn build_http_api_client(url: Url) -> Result<NymApiClient> {
|
||||
Ok(
|
||||
nym_http_api_client::Client::builder::<_, anyhow::Error>(url)?
|
||||
.no_hickory_dns()
|
||||
.with_user_agent("node-statistics-api")
|
||||
.build::<anyhow::Error>()?
|
||||
.into(),
|
||||
)
|
||||
fn build_http_api_client(url: Url) -> Result<Client> {
|
||||
Ok(Client::builder(url)?
|
||||
.no_hickory_dns()
|
||||
.with_user_agent("node-statistics-api")
|
||||
.build()?)
|
||||
}
|
||||
|
||||
async fn refresh_network_nodes(&mut self) -> Result<()> {
|
||||
|
||||
@@ -42,6 +42,7 @@ nym-credentials = { path = "../common/credentials" }
|
||||
nym-network-defaults = { path = "../common/network-defaults" }
|
||||
nym-task = { path = "../common/task" }
|
||||
nym-validator-client = { path = "../common/client-libs/validator-client" }
|
||||
nym-http-api-client = { path = "../common/http-api-client" }
|
||||
nym-coconut-dkg-common = { path = "../common/cosmwasm-smart-contracts/coconut-dkg" }
|
||||
nyxd-scraper = { path = "../common/nyxd-scraper" }
|
||||
nym-ticketbooks-merkle = { path = "../common/ticketbooks-merkle" }
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::rewarder::ticketbook_issuance::verifier::TicketbookIssuanceVerifier;
|
||||
use crate::rewarder::Rewarder;
|
||||
use anyhow::bail;
|
||||
use nym_ecash_time::ecash_default_expiration_date;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use time::macros::format_description;
|
||||
|
||||
@@ -15,7 +15,7 @@ use nym_validator_client::nyxd::module_traits::staking::{
|
||||
use nym_validator_client::nyxd::{
|
||||
AccountId, Coin, CosmWasmClient, Hash, PageRequest, StakingQueryClient,
|
||||
};
|
||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient, NymApiClient};
|
||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
@@ -139,10 +139,23 @@ impl NyxdClient {
|
||||
continue;
|
||||
};
|
||||
|
||||
let api_client = match nym_http_api_client::Client::builder(api_address)
|
||||
.and_then(|b| b.build())
|
||||
{
|
||||
Ok(client) => client,
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to create API client for issuer {}: {}",
|
||||
info.assigned_index, err
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
issuers.push(CredentialIssuer {
|
||||
public_key,
|
||||
operator_account: addr_to_account_id(share.owner),
|
||||
api_client: NymApiClient::new(api_address),
|
||||
api_client,
|
||||
verification_key,
|
||||
node_id: info.assigned_index,
|
||||
})
|
||||
|
||||
@@ -6,8 +6,8 @@ use cosmwasm_std::{Addr, Decimal, Uint128};
|
||||
use nym_coconut_dkg_common::types::NodeIndex;
|
||||
use nym_compact_ecash::VerificationKeyAuth;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::nyxd::{AccountId, Coin};
|
||||
use nym_validator_client::NymApiClient;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use tracing::info;
|
||||
|
||||
@@ -68,7 +68,7 @@ impl TicketbookIssuanceResults {
|
||||
pub struct CredentialIssuer {
|
||||
pub public_key: ed25519::PublicKey,
|
||||
pub operator_account: AccountId,
|
||||
pub api_client: NymApiClient,
|
||||
pub api_client: nym_http_api_client::Client,
|
||||
pub verification_key: VerificationKeyAuth,
|
||||
pub node_id: NodeIndex,
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use nym_validator_client::ecash::models::{
|
||||
IssuedTicketbooksChallengeCommitmentResponse, IssuedTicketbooksDataRequestBody,
|
||||
IssuedTicketbooksDataResponse, IssuedTicketbooksDataResponseBody, IssuedTicketbooksForResponse,
|
||||
};
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use nym_validator_client::signable::{SignableMessageBody, SignedMessage};
|
||||
use rand::distributions::{Distribution, WeightedIndex};
|
||||
|
||||
Generated
+51
@@ -3384,6 +3384,15 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.10"
|
||||
@@ -4216,20 +4225,34 @@ dependencies = [
|
||||
"encoding_rs",
|
||||
"hickory-resolver",
|
||||
"http 1.3.1",
|
||||
"inventory",
|
||||
"itertools 0.14.0",
|
||||
"mime",
|
||||
"nym-bin-common",
|
||||
"nym-http-api-client-macro",
|
||||
"nym-http-api-common",
|
||||
"once_cell",
|
||||
"reqwest 0.12.15",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"serde_yaml",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasmtimer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-http-api-client-macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.3.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-http-api-common"
|
||||
version = "0.1.0"
|
||||
@@ -6308,6 +6331,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.20"
|
||||
@@ -6370,6 +6402,19 @@ dependencies = [
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap 2.8.0",
|
||||
"itoa 1.0.15",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serdect"
|
||||
version = "0.2.0"
|
||||
@@ -7859,6 +7904,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
|
||||
@@ -2,7 +2,6 @@ use nym_contracts_common::signing::SigningAlgorithm;
|
||||
use nym_crypto::asymmetric::ed25519::Ed25519RecoveryError;
|
||||
use nym_node_requests::api::client::NymNodeApiClientError;
|
||||
use nym_types::error::TypesError;
|
||||
use nym_validator_client::nym_api::error::NymAPIError;
|
||||
use nym_validator_client::signing::direct_wallet::DirectSecp256k1HdWalletError;
|
||||
use nym_validator_client::{nyxd::error::NyxdError, ValidatorClientError};
|
||||
use nym_wallet_types::network::Network;
|
||||
@@ -45,11 +44,6 @@ pub enum BackendError {
|
||||
source: eyre::Report,
|
||||
},
|
||||
#[error(transparent)]
|
||||
NymApiError {
|
||||
#[from]
|
||||
source: NymAPIError,
|
||||
},
|
||||
#[error(transparent)]
|
||||
NymNodeApiError {
|
||||
#[from]
|
||||
source: NymNodeApiClientError,
|
||||
|
||||
@@ -15,7 +15,6 @@ use nym_mixnet_contract_common::nym_node::{NodeConfigUpdate, StakeSaturationResp
|
||||
use nym_mixnet_contract_common::{MixNodeConfigUpdate, NodeId, NymNode};
|
||||
use nym_node_requests::api::client::NymNodeApiClientExt;
|
||||
use nym_node_requests::api::v1::node::models::NodeDescription;
|
||||
use nym_node_requests::api::ErrorResponse;
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::gateway::GatewayBond;
|
||||
use nym_types::mixnode::{MixNodeDetails, NodeCostParams};
|
||||
@@ -586,14 +585,12 @@ pub async fn get_nym_node_description(
|
||||
port: u16,
|
||||
) -> Result<NodeDescription, BackendError> {
|
||||
Ok(
|
||||
nym_node_requests::api::Client::builder::<_, ErrorResponse>(format!(
|
||||
"http://{host}:{port}"
|
||||
))?
|
||||
.with_timeout(Duration::from_millis(1000))
|
||||
.with_user_agent(format!("nym-wallet/{}", env!("CARGO_PKG_VERSION")))
|
||||
.build::<ErrorResponse>()?
|
||||
.get_description()
|
||||
.await?,
|
||||
nym_node_requests::api::Client::builder(format!("http://{host}:{port}"))?
|
||||
.with_timeout(Duration::from_millis(1000))
|
||||
.with_user_agent(format!("nym-wallet/{}", env!("CARGO_PKG_VERSION")))
|
||||
.build()?
|
||||
.get_description()
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ nym-socks5-client-core = { path = "../../../common/socks5-client-core" }
|
||||
nym-validator-client = { path = "../../../common/client-libs/validator-client", features = [
|
||||
"http-client",
|
||||
] }
|
||||
nym-http-api-client = { path = "../../../common/http-api-client" }
|
||||
nym-socks5-requests = { path = "../../../common/socks5/requests" }
|
||||
nym-ordered-buffer = { path = "../../../common/socks5/ordered-buffer" }
|
||||
nym-service-providers-common = { path = "../../../service-providers/common" }
|
||||
|
||||
@@ -4,18 +4,22 @@
|
||||
use nym_sdk::mixnet;
|
||||
use nym_sdk::mixnet::MixnetMessageSender;
|
||||
use nym_topology::provider_trait::{async_trait, ToTopologyMetadata, TopologyProvider};
|
||||
use nym_topology::NymTopology;
|
||||
use nym_topology::{EpochRewardedSet, NymTopology};
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use url::Url;
|
||||
|
||||
struct MyTopologyProvider {
|
||||
validator_client: nym_validator_client::client::NymApiClient,
|
||||
validator_client: nym_http_api_client::Client,
|
||||
}
|
||||
|
||||
impl MyTopologyProvider {
|
||||
fn new(nym_api_url: Url) -> MyTopologyProvider {
|
||||
MyTopologyProvider {
|
||||
validator_client: nym_validator_client::client::NymApiClient::new(nym_api_url),
|
||||
}
|
||||
let validator_client = nym_http_api_client::Client::builder(nym_api_url)
|
||||
.expect("Failed to create API client builder")
|
||||
.build()
|
||||
.expect("Failed to build API client");
|
||||
|
||||
MyTopologyProvider { validator_client }
|
||||
}
|
||||
|
||||
async fn get_topology(&self) -> NymTopology {
|
||||
@@ -33,7 +37,8 @@ impl MyTopologyProvider {
|
||||
|
||||
let metadata = mixnodes_response.metadata.to_topology_metadata();
|
||||
|
||||
let mut base_topology = NymTopology::new(metadata, rewarded_set, Vec::new());
|
||||
let epoch_rewarded_set: EpochRewardedSet = rewarded_set.into();
|
||||
let mut base_topology = NymTopology::new(metadata, epoch_rewarded_set, Vec::new());
|
||||
|
||||
// in our topology provider only use mixnodes that have node_id divisible by 3
|
||||
// and has exactly 100 performance score
|
||||
|
||||
@@ -37,6 +37,7 @@ nym-crypto = { path = "../../../common/crypto", features = ["asymmetric", "rand"
|
||||
nym-config = { path = "../../../common/config" }
|
||||
nym-validator-client = { path = "../../../common/client-libs/validator-client" }
|
||||
nym-compact-ecash = { path = "../../../common/nym_offline_compact_ecash" }
|
||||
nym-http-api-client = { path = "../../../common/http-api-client" }
|
||||
dkg-bypass-contract = { path = "dkg-bypass-contract", default-features = false }
|
||||
|
||||
# contracts:
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::manager::network::LoadedNetwork;
|
||||
use crate::manager::NetworkManager;
|
||||
use console::style;
|
||||
use nym_config::{must_get_home, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR};
|
||||
use nym_validator_client::NymApiClient;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
@@ -91,7 +91,10 @@ impl NetworkManager {
|
||||
"⌛waiting for any gateway to appear in the directory ({api_url})..."
|
||||
));
|
||||
|
||||
let api_client = NymApiClient::new(api_url);
|
||||
let api_client = nym_http_api_client::Client::builder(api_url.clone())
|
||||
.expect("Failed to create API client builder")
|
||||
.build()
|
||||
.expect("Failed to build API client");
|
||||
|
||||
let wait_fut = async {
|
||||
let inner_fut = async {
|
||||
|
||||
@@ -25,6 +25,7 @@ time = { workspace = true }
|
||||
nym-validator-client = { path = "../../../common/client-libs/validator-client" }
|
||||
nym-bin-common = { path = "../../../common/bin-common", features = ["output_format", "basic_tracing"] }
|
||||
nym-network-defaults = { path = "../../../common/network-defaults" }
|
||||
nym-http-api-client = { path = "../../../common/http-api-client" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_validator_client::client::NymApiClientExt;
|
||||
use nym_validator_client::NymApiClient;
|
||||
use nym_validator_client::nym_api::NymApiClientExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
use strum::{Display, EnumProperty};
|
||||
@@ -48,8 +47,8 @@ impl SignerStatus {
|
||||
matches!(self.rpc_status, RpcStatus::Up)
|
||||
}
|
||||
|
||||
fn build_api_client(&self) -> Option<NymApiClient> {
|
||||
let api_endpoint = match self.api_endpoint.as_str().parse() {
|
||||
fn build_api_client(&self) -> Option<nym_http_api_client::Client> {
|
||||
let api_endpoint: nym_http_api_client::Url = match self.api_endpoint.as_str().parse() {
|
||||
Ok(endpoint) => endpoint,
|
||||
Err(err) => {
|
||||
error!("{} is not a valid api endpoint: {err}", self.api_endpoint);
|
||||
@@ -57,14 +56,17 @@ impl SignerStatus {
|
||||
}
|
||||
};
|
||||
|
||||
Some(NymApiClient::new(api_endpoint))
|
||||
nym_http_api_client::Client::builder(api_endpoint)
|
||||
.ok()?
|
||||
.build()
|
||||
.ok()
|
||||
}
|
||||
|
||||
pub(crate) async fn try_update_api_version(&mut self) {
|
||||
let Some(client) = self.build_api_client() else {
|
||||
return;
|
||||
};
|
||||
match client.nym_api.build_information().await {
|
||||
match client.build_information().await {
|
||||
Ok(build_info) => {
|
||||
self.api_version = ApiVersion::Available {
|
||||
version: build_info.build_version,
|
||||
@@ -84,7 +86,7 @@ impl SignerStatus {
|
||||
return;
|
||||
};
|
||||
|
||||
match client.nym_api.get_chain_status().await {
|
||||
match client.get_chain_status().await {
|
||||
Ok(chain_status) => {
|
||||
self.used_rpc_endpoint = RpcEndpoint(chain_status.connected_nyxd);
|
||||
let last_block =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::vpn_api_client::NymVpnApiClientError;
|
||||
use nym_http_api_client::HttpClientError;
|
||||
use thiserror::Error;
|
||||
use wasm_utils::wasm_error;
|
||||
|
||||
@@ -16,7 +16,7 @@ pub enum ZkNymError {
|
||||
#[error("failed to contact the vpn api")]
|
||||
HttpClientFailure {
|
||||
#[from]
|
||||
source: NymVpnApiClientError,
|
||||
source: HttpClientError,
|
||||
},
|
||||
#[error("the provided shares and issuers are not from the same epoch! {shares} and {issuers}")]
|
||||
InconsistentEpochId { shares: u64, issuers: u64 },
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::NymVpnApiClientError;
|
||||
use crate::error::ZkNymError;
|
||||
use crate::vpn_api_client::types::{
|
||||
AttributesResponse, MasterVerificationKeyResponse, PartialVerificationKeysResponse,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
pub use nym_http_api_client::Client;
|
||||
use nym_http_api_client::{parse_response, ApiClient, IntoUrl, PathSegments, NO_PARAMS};
|
||||
use nym_http_api_client::{
|
||||
parse_response, ApiClient, HttpClientError, IntoUrl, PathSegments, NO_PARAMS,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -34,13 +34,11 @@ pub fn new_client(
|
||||
#[allow(dead_code)]
|
||||
#[async_trait(?Send)]
|
||||
pub trait NymVpnApiClient {
|
||||
async fn simple_get<T>(&self, path: PathSegments<'_>) -> Result<T, NymVpnApiClientError>
|
||||
async fn simple_get<T>(&self, path: PathSegments<'_>) -> Result<T, HttpClientError>
|
||||
where
|
||||
T: DeserializeOwned;
|
||||
|
||||
async fn get_prehashed_public_attributes(
|
||||
&self,
|
||||
) -> Result<AttributesResponse, NymVpnApiClientError> {
|
||||
async fn get_prehashed_public_attributes(&self) -> Result<AttributesResponse, HttpClientError> {
|
||||
self.simple_get(&[
|
||||
"/api",
|
||||
"/v1",
|
||||
@@ -52,7 +50,7 @@ pub trait NymVpnApiClient {
|
||||
|
||||
async fn get_partial_verification_keys(
|
||||
&self,
|
||||
) -> Result<PartialVerificationKeysResponse, NymVpnApiClientError> {
|
||||
) -> Result<PartialVerificationKeysResponse, HttpClientError> {
|
||||
self.simple_get(&[
|
||||
"/api",
|
||||
"/v1",
|
||||
@@ -64,7 +62,7 @@ pub trait NymVpnApiClient {
|
||||
|
||||
async fn get_master_verification_key(
|
||||
&self,
|
||||
) -> Result<MasterVerificationKeyResponse, NymVpnApiClientError> {
|
||||
) -> Result<MasterVerificationKeyResponse, HttpClientError> {
|
||||
self.simple_get(&[
|
||||
"/api",
|
||||
"/v1",
|
||||
@@ -77,13 +75,13 @@ pub trait NymVpnApiClient {
|
||||
|
||||
#[async_trait(?Send)]
|
||||
impl NymVpnApiClient for VpnApiClient {
|
||||
async fn simple_get<T>(&self, path: PathSegments<'_>) -> Result<T, NymVpnApiClientError>
|
||||
async fn simple_get<T>(&self, path: PathSegments<'_>) -> Result<T, HttpClientError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let req = self
|
||||
.inner
|
||||
.create_get_request(path, NO_PARAMS)
|
||||
.create_get_request(path, NO_PARAMS)?
|
||||
.bearer_auth(&self.bearer_token)
|
||||
.send();
|
||||
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::vpn_api_client::types::ErrorResponse;
|
||||
use nym_http_api_client::HttpClientError;
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod client;
|
||||
|
||||
pub mod types;
|
||||
|
||||
pub type NymVpnApiClientError = HttpClientError<ErrorResponse>;
|
||||
|
||||
Reference in New Issue
Block a user