Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89228ae1e1 | |||
| c0cb98fee0 | |||
| 14a9991fa4 | |||
| a7c71ab3d4 | |||
| f26aad9880 |
Generated
+32
@@ -6573,6 +6573,38 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-payment-manager"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
"clap 4.3.21",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-network-defaults",
|
||||
"nym-payment-manager-common",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"rocket",
|
||||
"rocket_cors",
|
||||
"rocket_okapi",
|
||||
"schemars",
|
||||
"serde",
|
||||
"sqlx 0.6.3",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-payment-manager-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-pemstore"
|
||||
version = "0.3.0"
|
||||
|
||||
@@ -64,6 +64,7 @@ members = [
|
||||
"common/nymsphinx/params",
|
||||
"common/nymsphinx/routing",
|
||||
"common/nymsphinx/types",
|
||||
"common/payment-manager",
|
||||
"common/pemstore",
|
||||
"common/socks5-client-core",
|
||||
"common/socks5/proxy-helpers",
|
||||
@@ -88,6 +89,7 @@ members = [
|
||||
"service-providers/network-statistics",
|
||||
"nym-api",
|
||||
"nym-api/nym-api-requests",
|
||||
"nym-connect/payment-manager",
|
||||
"nym-outfox",
|
||||
"tools/nym-cli",
|
||||
"tools/nym-nr-query",
|
||||
|
||||
@@ -14,15 +14,15 @@ use std::path::PathBuf;
|
||||
pub struct Args {
|
||||
/// Config file of the client that is supposed to use the credential.
|
||||
#[clap(long)]
|
||||
pub(crate) client_config: PathBuf,
|
||||
pub client_config: PathBuf,
|
||||
|
||||
/// The amount of utokens the credential will hold.
|
||||
#[clap(long, default_value = "0")]
|
||||
pub(crate) amount: u64,
|
||||
pub amount: u64,
|
||||
|
||||
/// Path to a directory used to store recovery files for unconsumed deposits
|
||||
#[clap(long)]
|
||||
pub(crate) recovery_dir: PathBuf,
|
||||
pub recovery_dir: PathBuf,
|
||||
}
|
||||
|
||||
pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "nym-payment-manager-common"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
schemars = { version = "0.8", features = ["preserve_order"] }
|
||||
serde = { workspace = true }
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct PaymentResponse {
|
||||
pub unyms_bought: u64,
|
||||
}
|
||||
Generated
+409
-15
@@ -242,7 +242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
]
|
||||
@@ -254,7 +254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-lite",
|
||||
@@ -284,7 +284,7 @@ checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"blocking",
|
||||
"cfg-if",
|
||||
"event-listener",
|
||||
@@ -381,6 +381,15 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@@ -894,6 +903,15 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.1"
|
||||
@@ -969,6 +987,18 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comfy-table"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e959d788268e3bf9d35ace83e81b124190378e4c91c9067524675e33394b8ba"
|
||||
dependencies = [
|
||||
"crossterm",
|
||||
"strum 0.24.1",
|
||||
"strum_macros 0.24.3",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.2.0"
|
||||
@@ -1209,7 +1239,7 @@ version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset 0.9.0",
|
||||
@@ -1235,6 +1265,31 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot 0.12.1",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.4.9"
|
||||
@@ -2166,6 +2221,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "2.0.0"
|
||||
@@ -3143,7 +3204,7 @@ version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
@@ -3195,6 +3256,19 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "interprocess"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rustc_version",
|
||||
"to_method",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
@@ -3493,7 +3567,7 @@ version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
@@ -3596,7 +3670,7 @@ version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3605,7 +3679,7 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3643,6 +3717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
@@ -3768,7 +3843,7 @@ version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
@@ -3778,7 +3853,7 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
@@ -3789,7 +3864,7 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"libm",
|
||||
]
|
||||
|
||||
@@ -3875,9 +3950,59 @@ dependencies = [
|
||||
"pretty_env_logger",
|
||||
"semver 0.11.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"vergen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-cli-commands"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.13.1",
|
||||
"bip39",
|
||||
"bs58 0.4.0",
|
||||
"cfg-if",
|
||||
"clap",
|
||||
"comfy-table",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"cw-utils",
|
||||
"handlebars",
|
||||
"humantime-serde",
|
||||
"k256 0.13.1",
|
||||
"log",
|
||||
"nym-bandwidth-controller",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-coconut-bandwidth-contract-common",
|
||||
"nym-coconut-dkg-common",
|
||||
"nym-config",
|
||||
"nym-contracts-common",
|
||||
"nym-credential-storage",
|
||||
"nym-credential-utils",
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-multisig-contract-common",
|
||||
"nym-name-service-common",
|
||||
"nym-network-defaults",
|
||||
"nym-pemstore",
|
||||
"nym-service-provider-directory-common",
|
||||
"nym-sphinx",
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
"nym-vesting-contract-common",
|
||||
"rand 0.6.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tap",
|
||||
"thiserror",
|
||||
"time",
|
||||
"toml 0.5.11",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-client-core"
|
||||
version = "1.1.15"
|
||||
@@ -3996,6 +4121,7 @@ version = "1.1.19"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
"bs58 0.4.0",
|
||||
"dirs 4.0.0",
|
||||
"dotenvy",
|
||||
"eyre",
|
||||
@@ -4006,6 +4132,7 @@ dependencies = [
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-bin-common",
|
||||
"nym-cli-commands",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-contracts-common",
|
||||
@@ -4031,6 +4158,7 @@ dependencies = [
|
||||
"tauri-build",
|
||||
"tauri-codegen",
|
||||
"tauri-macros",
|
||||
"tauri-plugin-deep-link",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"time",
|
||||
@@ -4064,6 +4192,21 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-credential-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nym-bandwidth-controller",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-credential-storage",
|
||||
"nym-credentials",
|
||||
"nym-validator-client",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-credentials"
|
||||
version = "0.1.0"
|
||||
@@ -4578,6 +4721,30 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"itertools",
|
||||
"log",
|
||||
"nym-coconut-interface",
|
||||
"nym-config",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-validator-client",
|
||||
"nym-vesting-contract-common",
|
||||
"reqwest",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum 0.23.0",
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-validator-client"
|
||||
version = "0.1.0"
|
||||
@@ -4659,6 +4826,28 @@ dependencies = [
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-sys"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99e1d07c6eab1ce8b6382b8e3c7246fe117ff3f8b34be065f5ebace6749fe845"
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d"
|
||||
dependencies = [
|
||||
"objc-sys",
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666"
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
@@ -5197,7 +5386,7 @@ version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
@@ -5366,6 +5555,25 @@ version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"libc",
|
||||
"rand_chacha 0.1.1",
|
||||
"rand_core 0.4.2",
|
||||
"rand_hc 0.1.0",
|
||||
"rand_isaac",
|
||||
"rand_jitter",
|
||||
"rand_os",
|
||||
"rand_pcg 0.1.2",
|
||||
"rand_xorshift",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
@@ -5376,8 +5584,8 @@ dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.2.2",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc",
|
||||
"rand_pcg",
|
||||
"rand_hc 0.2.0",
|
||||
"rand_pcg 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5391,6 +5599,16 @@ dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
@@ -5411,6 +5629,21 @@ dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
@@ -5439,6 +5672,15 @@ dependencies = [
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
@@ -5448,6 +5690,50 @@ dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
dependencies = [
|
||||
"cloudabi",
|
||||
"fuchsia-cprng",
|
||||
"libc",
|
||||
"rand_core 0.4.2",
|
||||
"rdrand",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
dependencies = [
|
||||
"autocfg 0.1.8",
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
@@ -5457,6 +5743,15 @@ dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.5.2"
|
||||
@@ -5485,6 +5780,15 @@ dependencies = [
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
@@ -6331,6 +6635,17 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-mio"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
@@ -6378,7 +6693,7 @@ version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"autocfg 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6759,6 +7074,47 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
|
||||
dependencies = [
|
||||
"strum_macros 0.23.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
|
||||
dependencies = [
|
||||
"heck 0.3.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
@@ -7029,6 +7385,22 @@ dependencies = [
|
||||
"tauri-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-deep-link"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4536f5f6602e8fdfaa7b3b185076c2a0704f8eb7015f4e58461eb483ec3ed1f8"
|
||||
dependencies = [
|
||||
"dirs 5.0.1",
|
||||
"interprocess",
|
||||
"log",
|
||||
"objc2",
|
||||
"once_cell",
|
||||
"tauri-utils",
|
||||
"windows-sys 0.48.0",
|
||||
"winreg 0.50.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-runtime"
|
||||
version = "0.14.0"
|
||||
@@ -7332,6 +7704,12 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "to_method"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.31.0"
|
||||
@@ -7672,6 +8050,12 @@ version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_categories"
|
||||
version = "0.1.1"
|
||||
@@ -8421,6 +8805,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wry"
|
||||
version = "0.24.3"
|
||||
|
||||
@@ -21,6 +21,7 @@ tauri-macros = "^1.2.1"
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
bip39 = { version = "2.0.0", features = ["zeroize"] }
|
||||
bs58 = "0.4"
|
||||
dirs = "4.0"
|
||||
eyre = "0.6.5"
|
||||
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs", branch = "release"}
|
||||
@@ -38,6 +39,7 @@ serde_json = "1.0"
|
||||
serde_repr = "0.1"
|
||||
tap = "1.0.1"
|
||||
tauri = { version = "^1.2.2", features = ["clipboard-write-text", "macos-private-api", "notification-all", "shell-open", "system-tray", "updater", "window-close", "window-minimize", "window-start-dragging"] }
|
||||
tauri-plugin-deep-link = "0.1.1"
|
||||
#tendermint-rpc = "0.23.0"
|
||||
thiserror = "1.0"
|
||||
time = { version = "0.3.17", features = ["local-offset"] }
|
||||
@@ -51,6 +53,7 @@ dotenvy = "0.15.7"
|
||||
|
||||
nym-client-core = { path = "../../../common/client-core" }
|
||||
nym-api-requests = { path = "../../../nym-api/nym-api-requests" }
|
||||
nym-cli-commands = { path = "../../../common/commands" }
|
||||
nym-contracts-common = { path = "../../../common/cosmwasm-smart-contracts/contracts-common"}
|
||||
nym-config = { path = "../../../common/config" }
|
||||
nym-crypto = { path = "../../../common/crypto" }
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<!-- Add this file next to your tauri.conf.json file -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<!-- Obviously needs to be replaced with your app's bundle identifier -->
|
||||
<string>net.nymtech.connect</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<!-- register the myapp:// and myscheme:// schemes -->
|
||||
<string>nym-connect</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::{BackendError, Result};
|
||||
use bip39::Mnemonic;
|
||||
use nym_cli_commands::coconut::issue_credentials::Args as CoconutArgs;
|
||||
use nym_cli_commands::context::{create_signing_client, get_network_details, ClientArgs};
|
||||
use std::path::PathBuf;
|
||||
use url::Url;
|
||||
|
||||
pub async fn handle_url(url: &str) -> Result<()> {
|
||||
let url = Url::parse(url)?;
|
||||
if url.scheme() != env!("CARGO_PKG_NAME") {
|
||||
return Err(BackendError::InvalidURLScheme {
|
||||
scheme: url.scheme().to_string(),
|
||||
});
|
||||
}
|
||||
let bytes = bs58::decode(url.path()).into_vec()?;
|
||||
let mnemonic = Mnemonic::from_entropy(&bytes)?;
|
||||
|
||||
let args = ClientArgs {
|
||||
config_env_file: None,
|
||||
nyxd_url: None,
|
||||
nym_api_url: None,
|
||||
mnemonic: Some(mnemonic),
|
||||
mixnet_contract_address: None,
|
||||
vesting_contract_address: None,
|
||||
};
|
||||
let network_details = get_network_details(&args)?;
|
||||
let client = create_signing_client(args, &network_details)?;
|
||||
let coconut_args = CoconutArgs {
|
||||
client_config: Default::default(),
|
||||
amount: 10,
|
||||
recovery_dir: PathBuf::default(),
|
||||
};
|
||||
nym_cli_commands::coconut::issue_credentials::execute(coconut_args, client).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -111,6 +111,27 @@ pub enum BackendError {
|
||||
url: reqwest::Url,
|
||||
status_code: reqwest::StatusCode,
|
||||
},
|
||||
|
||||
#[error("the URL provided has an unrecognized scheme: {scheme}")]
|
||||
InvalidURLScheme { scheme: String },
|
||||
|
||||
#[error("{source}")]
|
||||
BS58DecodeError {
|
||||
#[from]
|
||||
source: bs58::decode::Error,
|
||||
},
|
||||
|
||||
#[error("{source}")]
|
||||
Bip39Error {
|
||||
#[from]
|
||||
source: bip39::Error,
|
||||
},
|
||||
|
||||
#[error("{source}")]
|
||||
ContextError {
|
||||
#[from]
|
||||
source: nym_cli_commands::context::errors::ContextError,
|
||||
},
|
||||
}
|
||||
|
||||
impl Serialize for BackendError {
|
||||
|
||||
@@ -18,6 +18,7 @@ use crate::window::window_toggle;
|
||||
|
||||
mod config;
|
||||
mod constants;
|
||||
// mod deep_links;
|
||||
mod error;
|
||||
mod events;
|
||||
mod logging;
|
||||
@@ -30,6 +31,7 @@ mod tasks;
|
||||
mod window;
|
||||
|
||||
fn main() {
|
||||
tauri_plugin_deep_link::prepare("nym-connect");
|
||||
dotenvy::dotenv().ok();
|
||||
|
||||
setup_env(env::args().nth(1).map(PathBuf::from).as_ref());
|
||||
@@ -112,7 +114,28 @@ fn main() {
|
||||
);
|
||||
}
|
||||
})
|
||||
.setup(move |app| Ok(crate::logging::setup_logging(app.app_handle(), monitoring)?))
|
||||
.setup(move |app| {
|
||||
let handle = app.handle();
|
||||
tauri_plugin_deep_link::register(env!("CARGO_PKG_NAME"), move |request| {
|
||||
let window = handle.windows();
|
||||
log::info!("Windows: {:?}", window.keys());
|
||||
if let Err(err) = window.emit("scheme-request-received", request) {
|
||||
log::error!("Failed to emit tauri event: {err}");
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// If you also need the url when the primary instance was started by the custom scheme, you currently have to read it yourself
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
// on macos the plugin handles this (macos doesn't use cli args for the url)
|
||||
if let Some(arg) = env::args().nth(1) {
|
||||
if let Err(e) = deep_links::handle_url(&arg) {
|
||||
log::error!("Could not handle URL {}: {:?}", request, e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(crate::logging::setup_logging(app.app_handle(), monitoring)?)
|
||||
})
|
||||
.system_tray(create_tray_menu())
|
||||
.on_system_tray_event(tray_menu_event_handler)
|
||||
.run(context)
|
||||
|
||||
@@ -8,10 +8,11 @@ use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn start_connecting(
|
||||
coconut_enabled: bool,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
window: tauri::Window<tauri::Wry>,
|
||||
) -> Result<ConnectResult> {
|
||||
log::trace!("Start connecting");
|
||||
log::info!("Start connecting with coconut enabled: {}", coconut_enabled);
|
||||
|
||||
let (msg_receiver, exit_status_receiver) = {
|
||||
let mut state_w = state.write().await;
|
||||
|
||||
@@ -38,7 +38,7 @@ export type TClientContext = {
|
||||
setShowInfoModal: (show: boolean) => void;
|
||||
setServiceProvider: () => void;
|
||||
setGateway: () => void;
|
||||
startConnecting: () => Promise<void>;
|
||||
startConnecting: (coconut_enabled: boolean) => Promise<void>;
|
||||
startDisconnecting: () => Promise<void>;
|
||||
setUserDefinedGateway: React.Dispatch<React.SetStateAction<UserDefinedGateway>>;
|
||||
setUserDefinedSPAddress: React.Dispatch<React.SetStateAction<UserDefinedSPAddress>>;
|
||||
@@ -139,15 +139,6 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
setGateways(fetchedGateways);
|
||||
};
|
||||
|
||||
useEvents({
|
||||
onError: (e) => {
|
||||
setError(e);
|
||||
Sentry.captureException(e);
|
||||
},
|
||||
onGatewayPerformanceChange: (performance) => setGatewayPerformance(performance),
|
||||
onStatusChange: (status) => setConnectionStatus(status),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
initialiseApp();
|
||||
}, []);
|
||||
@@ -160,9 +151,9 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const startConnecting = useCallback(async () => {
|
||||
const startConnecting = useCallback(async (value: boolean) => {
|
||||
try {
|
||||
await invoke('start_connecting');
|
||||
await invoke('start_connecting', { coconutEnabled: value });
|
||||
} catch (e) {
|
||||
setError({ title: 'Could not connect', message: e as string });
|
||||
console.log(e);
|
||||
@@ -243,6 +234,25 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => {
|
||||
await getUserData();
|
||||
};
|
||||
|
||||
const handleSchemeRequest = async () => {
|
||||
if (connectionStatus === 'disconnected') {
|
||||
await setServiceProvider();
|
||||
await setGateway();
|
||||
await startConnecting(true);
|
||||
setConnectedSince(DateTime.now());
|
||||
}
|
||||
};
|
||||
|
||||
useEvents({
|
||||
onError: (e) => {
|
||||
setError(e);
|
||||
Sentry.captureException(e);
|
||||
},
|
||||
onGatewayPerformanceChange: (performance) => setGatewayPerformance(performance),
|
||||
onStatusChange: (status) => setConnectionStatus(status),
|
||||
onSchemeRequest: handleSchemeRequest,
|
||||
});
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
mode,
|
||||
|
||||
@@ -11,10 +11,12 @@ export const useEvents = ({
|
||||
onError,
|
||||
onStatusChange,
|
||||
onGatewayPerformanceChange,
|
||||
onSchemeRequest,
|
||||
}: {
|
||||
onError: (error: Error) => void;
|
||||
onStatusChange: (status: ConnectionStatusKind) => void;
|
||||
onGatewayPerformanceChange: (status: GatewayPerformance) => void;
|
||||
onSchemeRequest: () => Promise<void>;
|
||||
}) => {
|
||||
const timerId = useRef<NodeJS.Timeout>();
|
||||
|
||||
@@ -65,6 +67,13 @@ export const useEvents = ({
|
||||
unlisten.push(result);
|
||||
});
|
||||
|
||||
listen('scheme-request-received', (e: TauriEvent) => {
|
||||
console.log(e);
|
||||
onSchemeRequest();
|
||||
}).then((result) => {
|
||||
unlisten.push(result);
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlisten.forEach((unsubscribe) => unsubscribe());
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ export const ConnectionPage = () => {
|
||||
Sentry.captureMessage('start connect', 'info');
|
||||
await context.setServiceProvider();
|
||||
await context.setGateway();
|
||||
await context.startConnecting();
|
||||
await context.startConnecting(false);
|
||||
context.setConnectedSince(DateTime.now());
|
||||
context.setShowInfoModal(true);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
[package]
|
||||
name = "nym-payment-manager"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
bip39 = { workspace = true }
|
||||
clap = { version = "4.0", features = ["cargo", "derive"] }
|
||||
lazy_static = "1.4.0"
|
||||
log = { workspace = true }
|
||||
schemars = { version = "0.8", features = ["preserve_order"] }
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "dfd3662c49e2f6fc37df35091cb94d82f7fb5915" }
|
||||
rocket_okapi = { version = "0.8.0-rc.2", features = ["swagger"] }
|
||||
serde = { workspace = true }
|
||||
sqlx = { version = "0.6.2", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
"macros",
|
||||
"migrate",
|
||||
] }
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.24.1", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
"signal",
|
||||
"time",
|
||||
] }
|
||||
|
||||
nym-bin-common = { path = "../../common/bin-common" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
nym-payment-manager-common = { path = "../../common/payment-manager" }
|
||||
nym-task = { path = "../../common/task" }
|
||||
nym-validator-client = { path = "../../common/client-libs/validator-client" }
|
||||
|
||||
[build-dependencies]
|
||||
sqlx = { version = "0.6.2", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
"macros",
|
||||
"migrate",
|
||||
] }
|
||||
tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] }
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
use std::env;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let database_path = format!("{}/nym-payment-manager-example.sqlite", out_dir);
|
||||
|
||||
let mut conn = SqliteConnection::connect(&format!("sqlite://{}?mode=rwc", database_path))
|
||||
.await
|
||||
.expect("Failed to create SQLx database connection");
|
||||
|
||||
sqlx::migrate!("./migrations")
|
||||
.run(&mut conn)
|
||||
.await
|
||||
.expect("Failed to perform SQLx migrations");
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
println!("cargo:rustc-env=DATABASE_URL=sqlite://{}", &database_path);
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
// for some strange reason we need to add a leading `/` to the windows path even though it's
|
||||
// not a valid windows path... but hey, it works...
|
||||
println!("cargo:rustc-env=DATABASE_URL=sqlite:///{}", &database_path);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE payments
|
||||
(
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
serial_number VARCHAR NOT NULL UNIQUE,
|
||||
unyms_bought INTEGER NOT NULL,
|
||||
paid BOOLEAN NOT NULL
|
||||
);
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use lazy_static::lazy_static;
|
||||
use nym_bin_common::bin_info;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PRETTY_BUILD_INFORMATION: String = bin_info!().pretty_print();
|
||||
}
|
||||
|
||||
// Helper for passing LONG_VERSION to clap
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
&PRETTY_BUILD_INFORMATION
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
|
||||
pub(crate) struct CliArgs {
|
||||
/// Path pointing to an env file that configures the Payment Manager.
|
||||
#[clap(short, long)]
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
/// Mnemonic of the Nym account holding the funds to be converted after successful payments
|
||||
#[clap(short, long)]
|
||||
pub(crate) mnemonic: bip39::Mnemonic,
|
||||
|
||||
/// Path pointing to the SQLite database containing payment data.
|
||||
#[clap(short, long)]
|
||||
pub(crate) db_path: std::path::PathBuf,
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::Error;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub(crate) struct Client(pub(crate) Arc<RwLock<DirectSigningHttpRpcNyxdClient>>);
|
||||
|
||||
impl Clone for Client {
|
||||
fn clone(&self) -> Self {
|
||||
Client(Arc::clone(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub(crate) fn new(
|
||||
details: &NymNetworkDetails,
|
||||
mnemonic: &bip39::Mnemonic,
|
||||
) -> Result<Self, Error> {
|
||||
let client_config = nyxd::Config::try_from_nym_network_details(details)?;
|
||||
let endpoint = details
|
||||
.endpoints
|
||||
.first()
|
||||
.ok_or(Error::EmptyValidatorList)?
|
||||
.nyxd_url
|
||||
.as_str();
|
||||
|
||||
let inner = DirectSigningHttpRpcNyxdClient::connect_with_mnemonic(
|
||||
client_config,
|
||||
endpoint,
|
||||
mnemonic.clone(),
|
||||
)?;
|
||||
|
||||
Ok(Client(Arc::new(RwLock::new(inner))))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use rocket::http::{ContentType, Status};
|
||||
use rocket::response::Responder;
|
||||
use rocket::{response, Request, Response};
|
||||
use rocket_okapi::gen::OpenApiGenerator;
|
||||
use rocket_okapi::okapi::openapi3::Responses;
|
||||
use rocket_okapi::response::OpenApiResponderInner;
|
||||
use rocket_okapi::util::ensure_status_code_exists;
|
||||
use std::io::Cursor;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("Database experienced an internal error - {0}")]
|
||||
InternalDatabaseError(#[from] sqlx::Error),
|
||||
|
||||
#[error("SQL migrate error - {0}")]
|
||||
DatabaseMigrateError(#[from] sqlx::migrate::MigrateError),
|
||||
|
||||
#[error("NyxdError - {0}")]
|
||||
NyxdError(#[from] nym_validator_client::nyxd::error::NyxdError),
|
||||
|
||||
#[error("Invalid payment requested")]
|
||||
InvalidPaymentRequest,
|
||||
|
||||
#[error("Bad deposit address")]
|
||||
BadAddress,
|
||||
|
||||
#[error("Empty list of validators")]
|
||||
EmptyValidatorList,
|
||||
}
|
||||
|
||||
impl<'r, 'o: 'r> Responder<'r, 'o> for Error {
|
||||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
|
||||
let err_msg = self.to_string();
|
||||
Response::build()
|
||||
.header(ContentType::Plain)
|
||||
.sized_body(err_msg.len(), Cursor::new(err_msg))
|
||||
.status(Status::BadRequest)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenApiResponderInner for Error {
|
||||
fn responses(_gen: &mut OpenApiGenerator) -> rocket_okapi::Result<Responses> {
|
||||
let mut responses = Responses::default();
|
||||
ensure_status_code_exists(&mut responses, 404);
|
||||
Ok(responses)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliArgs;
|
||||
use crate::client::Client;
|
||||
use crate::state::{Config, State};
|
||||
use crate::storage::Storage;
|
||||
use anyhow::Result;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use rocket::http::Method;
|
||||
use rocket::{Ignite, Rocket, Route};
|
||||
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors};
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::settings::OpenApiSettings;
|
||||
use rocket_okapi::swagger_ui::make_swagger_ui;
|
||||
use rocket_okapi::{mount_endpoints_and_merged_docs, openapi_get_routes_spec};
|
||||
|
||||
pub(crate) mod openapi;
|
||||
pub(crate) mod routes;
|
||||
|
||||
pub(crate) fn routes(settings: &OpenApiSettings) -> (Vec<Route>, OpenApi) {
|
||||
openapi_get_routes_spec![
|
||||
settings: routes::claim_payment,
|
||||
]
|
||||
}
|
||||
|
||||
fn setup_cors() -> Result<Cors> {
|
||||
let allowed_origins = AllowedOrigins::all();
|
||||
|
||||
// You can also deserialize this
|
||||
let cors = rocket_cors::CorsOptions {
|
||||
allowed_origins,
|
||||
allowed_methods: vec![Method::Post].into_iter().map(From::from).collect(),
|
||||
allowed_headers: AllowedHeaders::all(),
|
||||
allow_credentials: true,
|
||||
..Default::default()
|
||||
}
|
||||
.to_cors()?;
|
||||
|
||||
Ok(cors)
|
||||
}
|
||||
|
||||
pub(crate) async fn setup_rocket(args: &CliArgs) -> Result<Rocket<Ignite>> {
|
||||
let openapi_settings = rocket_okapi::settings::OpenApiSettings::default();
|
||||
let mut rocket = rocket::build();
|
||||
let storage = Storage::init(&args.db_path).await?;
|
||||
|
||||
mount_endpoints_and_merged_docs! {
|
||||
rocket,
|
||||
"/v1".to_owned(),
|
||||
openapi_settings,
|
||||
"/" => (vec![], openapi::custom_openapi_spec()),
|
||||
"" => routes(&openapi_settings),
|
||||
}
|
||||
|
||||
let details = NymNetworkDetails::new_from_env();
|
||||
let client = Client::new(&details, &args.mnemonic)?;
|
||||
let config = Config::new(details.chain_details.mix_denom.base.clone());
|
||||
let rocket = rocket
|
||||
.manage(State::new(storage, client, config))
|
||||
.mount("/swagger", make_swagger_ui(&openapi::get_docs()))
|
||||
.attach(setup_cors()?);
|
||||
|
||||
Ok(rocket.ignite().await?)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use rocket_okapi::okapi::openapi3::OpenApi;
|
||||
use rocket_okapi::swagger_ui::SwaggerUIConfig;
|
||||
|
||||
pub fn custom_openapi_spec() -> OpenApi {
|
||||
use rocket_okapi::okapi::openapi3::*;
|
||||
OpenApi {
|
||||
openapi: OpenApi::default_version(),
|
||||
info: Info {
|
||||
title: "Nym Payment Manager".to_owned(),
|
||||
description: None,
|
||||
terms_of_service: None,
|
||||
contact: None,
|
||||
license: None,
|
||||
version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||
..Default::default()
|
||||
},
|
||||
servers: get_servers(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_servers() -> Vec<rocket_okapi::okapi::openapi3::Server> {
|
||||
if std::env::var_os("CARGO").is_some() {
|
||||
return vec![];
|
||||
}
|
||||
vec![rocket_okapi::okapi::openapi3::Server {
|
||||
url: std::env::var("OPEN_API_BASE").unwrap_or_else(|_| "/v1/".to_owned()),
|
||||
description: Some("Payment Manager".to_owned()),
|
||||
..Default::default()
|
||||
}]
|
||||
}
|
||||
|
||||
pub(crate) fn get_docs() -> SwaggerUIConfig {
|
||||
SwaggerUIConfig {
|
||||
url: "../v1/openapi.json".to_owned(),
|
||||
..SwaggerUIConfig::default()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::state::State;
|
||||
use nym_payment_manager_common::PaymentResponse;
|
||||
use nym_validator_client::nyxd::{AccountId, Coin};
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{post, State as RocketState};
|
||||
use rocket_okapi::okapi::schemars;
|
||||
use rocket_okapi::openapi;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
// All strings are base58 encoded representations of structs
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct ClaimPaymentRequestBody {
|
||||
pub serial_number: String,
|
||||
pub deposit_address: String,
|
||||
}
|
||||
|
||||
#[openapi(tag = "payment")]
|
||||
#[post("/claim_payment", data = "<claim_payment_request_body>")]
|
||||
pub async fn claim_payment(
|
||||
claim_payment_request_body: Json<ClaimPaymentRequestBody>,
|
||||
state: &RocketState<State>,
|
||||
) -> Result<Json<PaymentResponse>, Error> {
|
||||
let payment = state
|
||||
.storage
|
||||
.manager
|
||||
.get_payment(&claim_payment_request_body.serial_number)
|
||||
.await?
|
||||
.ok_or(Error::InvalidPaymentRequest)?;
|
||||
|
||||
let recipient = AccountId::from_str(&claim_payment_request_body.deposit_address)
|
||||
.map_err(|_| Error::BadAddress)?;
|
||||
let amount = vec![Coin::new(
|
||||
payment.unyms_bought as u128,
|
||||
state.config.denom(),
|
||||
)];
|
||||
state
|
||||
.client
|
||||
.0
|
||||
.read()
|
||||
.await
|
||||
.send(&recipient, amount, "deposit via payment", None)
|
||||
.await?;
|
||||
|
||||
state.storage.manager.update_payment(payment.id).await?;
|
||||
|
||||
Ok(Json(PaymentResponse {
|
||||
unyms_bought: payment.unyms_bought as u64,
|
||||
}))
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use clap::Parser;
|
||||
use nym_bin_common::logging::setup_logging;
|
||||
use nym_network_defaults::setup_env;
|
||||
use nym_task::TaskManager;
|
||||
use std::error::Error;
|
||||
|
||||
mod cli;
|
||||
mod client;
|
||||
mod error;
|
||||
mod http;
|
||||
mod state;
|
||||
mod storage;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
setup_logging();
|
||||
let args = cli::CliArgs::parse();
|
||||
setup_env(args.config_env_file.as_ref());
|
||||
|
||||
// let's build our rocket!
|
||||
let rocket = http::setup_rocket(&args).await?;
|
||||
|
||||
// setup shutdowns
|
||||
let shutdown = TaskManager::new(10);
|
||||
let rocket_shutdown_handle = rocket.shutdown();
|
||||
|
||||
// launch rocket
|
||||
tokio::spawn(rocket.launch());
|
||||
|
||||
// wait for termination
|
||||
shutdown.catch_interrupt().await.ok();
|
||||
rocket_shutdown_handle.notify();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::Client;
|
||||
use crate::storage::Storage;
|
||||
|
||||
pub struct Config {
|
||||
denom: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(denom: String) -> Self {
|
||||
Config { denom }
|
||||
}
|
||||
|
||||
pub fn denom(&self) -> &str {
|
||||
&self.denom
|
||||
}
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
pub(crate) storage: Storage,
|
||||
pub(crate) client: Client,
|
||||
pub(crate) config: Config,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub(crate) fn new(storage: Storage, client: Client, config: Config) -> Self {
|
||||
State {
|
||||
storage,
|
||||
client,
|
||||
config,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::storage::models::Payment;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct StorageManager {
|
||||
pub(crate) connection_pool: sqlx::SqlitePool,
|
||||
}
|
||||
|
||||
// all SQL goes here
|
||||
impl StorageManager {
|
||||
pub(crate) async fn get_payment(
|
||||
&self,
|
||||
serial_number: &str,
|
||||
) -> Result<Option<Payment>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Payment,
|
||||
r#"
|
||||
SELECT *
|
||||
FROM payments
|
||||
WHERE serial_number = ?
|
||||
"#,
|
||||
serial_number
|
||||
)
|
||||
.fetch_optional(&self.connection_pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn update_payment(&self, id: i64) -> Result<(), sqlx::Error> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
UPDATE payments
|
||||
SET paid = true
|
||||
WHERE id = ?
|
||||
"#,
|
||||
id
|
||||
)
|
||||
.execute(&self.connection_pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use log::*;
|
||||
use manager::StorageManager;
|
||||
use sqlx::ConnectOptions;
|
||||
use std::path::Path;
|
||||
|
||||
mod manager;
|
||||
mod models;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Storage {
|
||||
pub manager: StorageManager,
|
||||
}
|
||||
|
||||
impl Storage {
|
||||
pub async fn init<P: AsRef<Path>>(database_path: P) -> Result<Self, crate::error::Error> {
|
||||
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
|
||||
.filename(database_path)
|
||||
.create_if_missing(true);
|
||||
|
||||
// TODO: do we want auto_vacuum ?
|
||||
|
||||
opts.disable_statement_logging();
|
||||
|
||||
let connection_pool = match sqlx::SqlitePool::connect_with(opts).await {
|
||||
Ok(db) => db,
|
||||
Err(err) => {
|
||||
error!("Failed to connect to SQLx database: {err}");
|
||||
return Err(err.into());
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = sqlx::migrate!("./migrations").run(&connection_pool).await {
|
||||
error!("Failed to initialize SQLx database: {err}");
|
||||
return Err(err.into());
|
||||
}
|
||||
|
||||
info!("Database migration finished!");
|
||||
|
||||
let storage = Storage {
|
||||
manager: StorageManager { connection_pool },
|
||||
};
|
||||
|
||||
Ok(storage)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) struct Payment {
|
||||
pub(crate) id: i64,
|
||||
pub(crate) serial_number: String,
|
||||
pub(crate) unyms_bought: i64,
|
||||
pub(crate) paid: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)]
|
||||
pub struct PaymentResponse {
|
||||
pub unyms_bought: u64,
|
||||
}
|
||||
Reference in New Issue
Block a user