Compare commits

...

5 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacșu 89228ae1e1 Catch and emit event in backend for URL opening
The JS part of listening to that event is still not working, probably
due to some window init race. Needs to be investigated more.
2023-09-05 22:16:03 +03:00
Bogdan-Ștefan Neacșu c0cb98fee0 Better error message on invalid payment req 2023-09-04 14:29:33 +03:00
Bogdan-Ștefan Neacșu 14a9991fa4 Use clap arguments 2023-09-04 14:29:33 +03:00
Bogdan-Ștefan Neacșu a7c71ab3d4 Introduce nyxd client 2023-09-04 14:29:33 +03:00
Bogdan-Ștefan Neacșu f26aad9880 Add payment manager 2023-09-04 14:29:33 +03:00
29 changed files with 1157 additions and 33 deletions
Generated
+32
View File
@@ -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"
+2
View File
@@ -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<()> {
+15
View File
@@ -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 }
+9
View File
@@ -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,
}
+409 -15
View File
@@ -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"
+3
View File
@@ -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" }
+20
View File
@@ -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 {
+24 -1
View File
@@ -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;
+22 -12
View File
@@ -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,
+9
View File
@@ -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;
+46
View File
@@ -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"] }
+28
View File
@@ -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
);
+31
View File
@@ -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,
}
+39
View File
@@ -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))))
}
}
+52
View File
@@ -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,
}))
}
+38
View File
@@ -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(())
}
+35
View File
@@ -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,
}