Compare commits
53 Commits
ls
...
coin-experimenting
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e5923eaad | |||
| c5350f30aa | |||
| 7ffc8b9999 | |||
| 7c9fbc9c73 | |||
| 2bcdc4c3d0 | |||
| 8300daa117 | |||
| a60de5764d | |||
| 23b093349d | |||
| 8955ee0b1d | |||
| 9ef87df573 | |||
| ce7717fb2a | |||
| 24c146766d | |||
| b6ddaebe67 | |||
| 282b18660f | |||
| b248f2e4b5 | |||
| 184dd7767d | |||
| 2483a545b7 | |||
| df1926071a | |||
| 81a206f6c0 | |||
| 87e8666b86 | |||
| 3519d0c31d | |||
| dbbd94d64c | |||
| 93705d83ab | |||
| 66b71fe87b | |||
| 4f20085c05 | |||
| a33c21d438 | |||
| 04d02b08bc | |||
| 9460276131 | |||
| 84c9394eba | |||
| 6030d3831f | |||
| 241f0cf93a | |||
| 11122635f9 | |||
| ea54a3edc2 | |||
| 985a38429d | |||
| c9f821864a | |||
| 37d55f3a06 | |||
| b2ce142c17 | |||
| 374baa5ec1 | |||
| de1df74eb5 | |||
| 766c31544e | |||
| ecca7e8479 | |||
| 84a42f6ed9 | |||
| 5925e85684 | |||
| 972c60726c | |||
| ece22b9703 | |||
| 3f718feb41 | |||
| b550c32db6 | |||
| 83090c0a25 | |||
| 97ad1a2e46 | |||
| 9fbefa34e8 | |||
| 0812296399 | |||
| 51b04081a3 | |||
| 7f2027ca6b |
Generated
+84
-2
@@ -218,9 +218,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179"
|
||||
checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b"
|
||||
|
||||
[[package]]
|
||||
name = "binascii"
|
||||
@@ -3204,6 +3204,32 @@ dependencies = [
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"coconut-interface",
|
||||
"config",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"itertools",
|
||||
"log",
|
||||
"mixnet-contract-common",
|
||||
"reqwest",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vesting-contract",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-validator-api"
|
||||
version = "1.0.1"
|
||||
@@ -3251,6 +3277,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"topology",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-api-requests",
|
||||
"validator-client",
|
||||
@@ -3258,6 +3285,24 @@ dependencies = [
|
||||
"version-checker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"config",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"mixnet-contract-common",
|
||||
"nym-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum",
|
||||
"ts-rs",
|
||||
"validator-client",
|
||||
"vesting-contract",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nymcoconut"
|
||||
version = "0.5.0"
|
||||
@@ -5399,6 +5444,28 @@ 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",
|
||||
]
|
||||
|
||||
[[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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
@@ -6025,6 +6092,21 @@ dependencies = [
|
||||
"ts-rs-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"mixnet-contract-common",
|
||||
"nym-types",
|
||||
"nym-wallet-types",
|
||||
"ts-rs",
|
||||
"validator-api-requests",
|
||||
"validator-client",
|
||||
"vesting-contract-common",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-macros"
|
||||
version = "6.1.2"
|
||||
|
||||
+3
-1
@@ -58,6 +58,7 @@ members = [
|
||||
"common/socks5/requests",
|
||||
"common/task",
|
||||
"common/topology",
|
||||
"common/types",
|
||||
"common/wasm-utils",
|
||||
"explorer-api",
|
||||
"gateway",
|
||||
@@ -67,6 +68,7 @@ members = [
|
||||
"service-providers/network-statistics",
|
||||
"validator-api",
|
||||
"validator-api/validator-api-requests",
|
||||
"tools/ts-rs-cli"
|
||||
]
|
||||
|
||||
default-members = [
|
||||
@@ -79,4 +81,4 @@ default-members = [
|
||||
"explorer-api",
|
||||
]
|
||||
|
||||
exclude = ["explorer", "contracts", "tokenomics-py", "clients/webassembly"]
|
||||
exclude = ["explorer", "contracts", "tokenomics-py", "clients/webassembly", "nym-wallet"]
|
||||
|
||||
@@ -54,3 +54,7 @@ fmt-wallet:
|
||||
|
||||
wasm:
|
||||
RUSTFLAGS='-C link-arg=-s' cargo build --manifest-path contracts/Cargo.toml --release --target wasm32-unknown-unknown
|
||||
|
||||
generate-typescript:
|
||||
cd tools/ts-rs-cli && cargo run && cd ../..
|
||||
yarn types:lint:fix
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M171.7,30.3001 C132.7,-8.7999 69.3001,-8.7999 30.3001,30.3001 C-8.7999,69.4001 -8.7999,132.7 30.3001,171.7 C69.4001,210.8 132.7,210.8 171.7,171.7 C210.8,132.7 210.8,69.3001 171.7,30.3001 Z M163.1,163.1 C128.8,197.4 73.1001,197.4 38.8001,163.1 C4.5001,128.8 4.5001,73.1001 38.8001,38.8001 C73.1001,4.5001 128.8,4.5001 163.1,38.8001 C197.5,73.2001 197.5,128.8 163.1,163.1 Z" id="Shape" fill="#fff"></path>
|
||||
<path d="M163.1,38.9 C128.8,4.60005 73.1002,4.60005 38.8002,38.9 C4.50019,73.2 4.50019,128.9 38.8002,163.2 C73.1002,197.5 128.8,197.5 163.1,163.2 C197.5,128.8 197.5,73.2 163.1,38.9 Z" id="Shape" fill="#000"></path>
|
||||
<g id="T" transform="translate(25, 25) scale(5,5)">
|
||||
<path d="M18.4804688,24 C19.203125,24 19.7182617,23.8608398 20.0258789,23.5825195 C20.3334961,23.3041992 20.4873047,22.9453125 20.4873047,22.5058594 C20.4873047,22.0566406 20.3334961,21.6928711 20.0258789,21.4145508 C19.7182617,21.1362305 19.203125,20.9970703 18.4804688,20.9970703 L18.4804688,20.9970703 L16.4589844,20.9970703 L16.4589844,9.24902344 L19.7548828,9.24902344 L19.7548828,12.0908203 C19.7548828,12.8134766 19.894043,13.3286133 20.1723633,13.6362305 C20.4506836,13.9438477 20.8095703,14.0976562 21.2490234,14.0976562 C21.6982422,14.0976562 22.0620117,13.9438477 22.340332,13.6362305 C22.6186523,13.3286133 22.7578125,12.8134766 22.7578125,12.0908203 L22.7578125,12.0908203 L22.7578125,6.24609375 L7.20117188,6.23144531 L7.20117188,12.0908203 C7.20117188,12.8134766 7.34033203,13.3286133 7.61865234,13.6362305 C7.89697266,13.9438477 8.25585938,14.0976562 8.6953125,14.0976562 C9.14453125,14.0976562 9.50830078,13.9438477 9.78662109,13.6362305 C10.0649414,13.3286133 10.2041016,12.8134766 10.2041016,12.0908203 L10.2041016,12.0908203 L10.2041016,9.24902344 L13.4560547,9.24902344 L13.4560547,20.9970703 L11.4492188,20.9970703 C10.7265625,20.9970703 10.2114258,21.1362305 9.90380859,21.4145508 C9.59619141,21.6928711 9.44238281,22.0517578 9.44238281,22.4912109 C9.44238281,22.9404297 9.59619141,23.3041992 9.90380859,23.5825195 C10.2114258,23.8608398 10.7265625,24 11.4492188,24 L11.4492188,24 L18.4804688,24 Z" id="T" fill="#fff"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M170.7 29.3001C131.7 -9.7999 68.3001 -9.7999 29.3001 29.3001C-9.7999 68.4001 -9.7999 131.7 29.3001 170.7C68.4001 209.8 131.7 209.8 170.7 170.7C209.8 131.7 209.8 68.3001 170.7 29.3001ZM162.1 162.1C127.8 196.4 72.1001 196.4 37.8001 162.1C3.5001 127.8 3.5001 72.1001 37.8001 37.8001C72.1001 3.5001 127.8 3.5001 162.1 37.8001C196.5 72.2001 196.5 127.8 162.1 162.1Z" fill="white"/>
|
||||
<path d="M162.1 37.9C127.8 3.60005 72.1002 3.60005 37.8002 37.9C3.50019 72.2 3.50019 127.9 37.8002 162.2C72.1002 196.5 127.8 196.5 162.1 162.2C196.5 127.8 196.5 72.2 162.1 37.9ZM63.0002 170.7C56.8002 167.4 51.1002 163.2 46.1002 158.4V41.7C51.3002 36.7 57.2002 32.5 63.6002 29.1L137 140.9V29.3C143.2 32.6 148.9 36.8 153.9 41.6V158.3C148.7 163.3 142.8 167.5 136.4 170.9L63.0002 59.1V170.7Z" fill="#070B15"/>
|
||||
<path d="M154 158.3V41.7C148.9 36.9 143.2 32.7 137.1 29.4V140.9L63.5 29C57.1 32.4 51.2 36.6 46 41.6V158.3C51.1 163.1 56.8 167.3 62.9 170.6V59.1L136.5 171C142.9 167.6 148.8 163.3 154 158.3Z" fill="white"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,7 @@
|
||||
<svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M171.7,30.3001 C132.7,-8.7999 69.3001,-8.7999 30.3001,30.3001 C-8.7999,69.4001 -8.7999,132.7 30.3001,171.7 C69.4001,210.8 132.7,210.8 171.7,171.7 C210.8,132.7 210.8,69.3001 171.7,30.3001 Z M163.1,163.1 C128.8,197.4 73.1001,197.4 38.8001,163.1 C4.5001,128.8 4.5001,73.1001 38.8001,38.8001 C73.1001,4.5001 128.8,4.5001 163.1,38.8001 C197.5,73.2001 197.5,128.8 163.1,163.1 Z" id="Shape" fill="#141521"></path>
|
||||
<path d="M163.1,38.9 C128.8,4.60005 73.1002,4.60005 38.8002,38.9 C4.50019,73.2 4.50019,128.9 38.8002,163.2 C73.1002,197.5 128.8,197.5 163.1,163.2 C197.5,128.8 197.5,73.2 163.1,38.9 Z" id="Shape" fill="#FFFFFF"></path>
|
||||
<g id="T" transform="translate(25, 25) scale(5,5)">
|
||||
<path d="M18.4804688,24 C19.203125,24 19.7182617,23.8608398 20.0258789,23.5825195 C20.3334961,23.3041992 20.4873047,22.9453125 20.4873047,22.5058594 C20.4873047,22.0566406 20.3334961,21.6928711 20.0258789,21.4145508 C19.7182617,21.1362305 19.203125,20.9970703 18.4804688,20.9970703 L18.4804688,20.9970703 L16.4589844,20.9970703 L16.4589844,9.24902344 L19.7548828,9.24902344 L19.7548828,12.0908203 C19.7548828,12.8134766 19.894043,13.3286133 20.1723633,13.6362305 C20.4506836,13.9438477 20.8095703,14.0976562 21.2490234,14.0976562 C21.6982422,14.0976562 22.0620117,13.9438477 22.340332,13.6362305 C22.6186523,13.3286133 22.7578125,12.8134766 22.7578125,12.0908203 L22.7578125,12.0908203 L22.7578125,6.24609375 L7.20117188,6.23144531 L7.20117188,12.0908203 C7.20117188,12.8134766 7.34033203,13.3286133 7.61865234,13.6362305 C7.89697266,13.9438477 8.25585938,14.0976562 8.6953125,14.0976562 C9.14453125,14.0976562 9.50830078,13.9438477 9.78662109,13.6362305 C10.0649414,13.3286133 10.2041016,12.8134766 10.2041016,12.0908203 L10.2041016,12.0908203 L10.2041016,9.24902344 L13.4560547,9.24902344 L13.4560547,20.9970703 L11.4492188,20.9970703 C10.7265625,20.9970703 10.2114258,21.1362305 9.90380859,21.4145508 C9.59619141,21.6928711 9.44238281,22.0517578 9.44238281,22.4912109 C9.44238281,22.9404297 9.59619141,23.3041992 9.90380859,23.5825195 C10.2114258,23.8608398 10.7265625,24 11.4492188,24 L11.4492188,24 L18.4804688,24 Z" id="T" fill="#000" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M170.7 29.3001C131.7 -9.7999 68.3001 -9.7999 29.3001 29.3001C-9.7999 68.4001 -9.7999 131.7 29.3001 170.7C68.4001 209.8 131.7 209.8 170.7 170.7C209.8 131.7 209.8 68.3001 170.7 29.3001ZM162.1 162.1C127.8 196.4 72.1001 196.4 37.8001 162.1C3.5001 127.8 3.5001 72.1001 37.8001 37.8001C72.1001 3.5001 127.8 3.5001 162.1 37.8001C196.5 72.2001 196.5 127.8 162.1 162.1Z" fill="#141521"/>
|
||||
<path d="M162.1 37.9C127.8 3.60005 72.1002 3.60005 37.8002 37.9C3.50019 72.2 3.50019 127.9 37.8002 162.2C72.1002 196.5 127.8 196.5 162.1 162.2C196.5 127.8 196.5 72.2 162.1 37.9ZM63.0002 170.7C56.8002 167.4 51.1002 163.2 46.1002 158.4V41.7C51.3002 36.7 57.2002 32.5 63.6002 29.1L137 140.9V29.3C143.2 32.6 148.9 36.8 153.9 41.6V158.3C148.7 163.3 142.8 167.5 136.4 170.9L63.0002 59.1V170.7Z" fill="white"/>
|
||||
<path d="M154 158.3V41.7C148.9 36.9 143.2 32.7 137.1 29.4V140.9L63.5 29C57.1 32.4 51.2 36.6 46 41.6V158.3C51.1 163.1 56.8 167.3 62.9 170.6V59.1L136.5 171C142.9 167.6 148.8 163.3 154 158.3Z" fill="#141521"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -8,7 +8,7 @@ use url::Url;
|
||||
use crate::error::Result;
|
||||
use crate::{MNEMONIC, NYMD_URL};
|
||||
|
||||
use network_defaults::{DEFAULT_NETWORK, DENOM, VOUCHER_INFO};
|
||||
use network_defaults::{DEFAULT_NETWORK, MIX_DENOM, VOUCHER_INFO};
|
||||
use validator_client::nymd::traits::CoconutBandwidthSigningClient;
|
||||
use validator_client::nymd::{Coin, Fee, NymdClient, SigningNymdClient};
|
||||
|
||||
@@ -34,7 +34,7 @@ impl Client {
|
||||
encryption_key: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<String> {
|
||||
let amount = Coin::new(amount as u128, DENOM.to_string());
|
||||
let amount = Coin::new(amount as u128, MIX_DENOM.base.to_string());
|
||||
Ok(self
|
||||
.nymd_client
|
||||
.deposit(
|
||||
|
||||
@@ -43,7 +43,6 @@ itertools = { version = "0.10", optional = true }
|
||||
cosmwasm-std = { version = "1.0.0", optional = true }
|
||||
execute = { path = "../../execute" }
|
||||
|
||||
[dev-dependencies]
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
[features]
|
||||
@@ -58,3 +57,5 @@ nymd-client = [
|
||||
"itertools",
|
||||
"cosmwasm-std",
|
||||
]
|
||||
generate-ts = []
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ use cosmrs::rpc::{self, HttpClient, Order};
|
||||
use cosmrs::tendermint::abci::Code as AbciCode;
|
||||
use cosmrs::tendermint::abci::Transaction;
|
||||
use cosmrs::tendermint::{abci, block, chain};
|
||||
use cosmrs::{tx, AccountId, Coin as CosmosCoin, Denom, Tx};
|
||||
use cosmrs::{tx, AccountId, Coin as CosmosCoin, Tx};
|
||||
use prost::Message;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
@@ -121,7 +121,7 @@ pub trait CosmWasmClient: rpc::Client {
|
||||
async fn get_balance(
|
||||
&self,
|
||||
address: &AccountId,
|
||||
search_denom: Denom,
|
||||
search_denom: String,
|
||||
) -> Result<Option<Coin>, NymdError> {
|
||||
let path = Some("/cosmos.bank.v1beta1.Query/Balance".parse().unwrap());
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
use crate::nymd::error::NymdError;
|
||||
use cosmrs::tendermint::abci;
|
||||
use itertools::Itertools;
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// it seems that currently validators just emit stringified events (which are also returned as part of deliverTx response)
|
||||
// as theirs logs
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Log {
|
||||
#[serde(default)]
|
||||
// weird thing is that the first msg_index seems to always be undefined on the raw logs
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nymd::Coin;
|
||||
use cosmrs::tx;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub mod gas_price;
|
||||
|
||||
@@ -14,6 +16,40 @@ pub enum Fee {
|
||||
Auto(Option<f32>),
|
||||
}
|
||||
|
||||
impl Display for Fee {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Fee::Manual(fee) => {
|
||||
write!(f, "Fee in manual mode with ")?;
|
||||
for fee in &fee.amount {
|
||||
write!(f, "{}{} paid in fees, ", fee.amount, fee.denom)?;
|
||||
}
|
||||
write!(f, "{} set as gas limit, ", fee.gas_limit)?;
|
||||
if let Some(payer) = &fee.payer {
|
||||
write!(f, "{payer} set as payer, ")?;
|
||||
}
|
||||
if let Some(granter) = &fee.granter {
|
||||
write!(f, "{granter} set as granter")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Fee::Auto(Some(multiplier)) => {
|
||||
write!(f, "Fee in auto mode with {multiplier} simulated multiplier")
|
||||
}
|
||||
Fee::Auto(None) => write!(f, "Fee in auto mode with no custom simulated multiplier"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Fee {
|
||||
pub fn try_get_manual_amount(&self) -> Option<Vec<Coin>> {
|
||||
match self {
|
||||
Fee::Manual(tx_fee) => Some(tx_fee.amount.iter().cloned().map(Into::into).collect()),
|
||||
Fee::Auto(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tx::Fee> for Fee {
|
||||
fn from(fee: tx::Fee) -> Self {
|
||||
Fee::Manual(fee)
|
||||
|
||||
@@ -134,7 +134,7 @@ impl NymdClient<SigningNymdClient> {
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let denom = network.denom();
|
||||
let denom = network.mix_denom().base;
|
||||
let client_address = signer
|
||||
.try_derive_accounts()?
|
||||
.into_iter()
|
||||
@@ -176,7 +176,7 @@ impl NymdClient<SigningNymdClient> {
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let prefix = network.bech32_prefix();
|
||||
let denom = network.denom();
|
||||
let denom = network.mix_denom().base;
|
||||
let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic)?;
|
||||
let client_address = wallet
|
||||
.try_derive_accounts()?
|
||||
@@ -289,7 +289,17 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
{
|
||||
Ok(self.client.get_block(None).await?.block.header.time)
|
||||
self.get_block_timestamp(None).await
|
||||
}
|
||||
|
||||
pub async fn get_block_timestamp(
|
||||
&self,
|
||||
height: Option<u32>,
|
||||
) -> Result<TendermintTime, NymdError>
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
{
|
||||
Ok(self.client.get_block(height).await?.block.header.time)
|
||||
}
|
||||
|
||||
pub async fn get_current_block_height(&self) -> Result<Height, NymdError>
|
||||
@@ -328,7 +338,7 @@ impl<C> NymdClient<C> {
|
||||
pub async fn get_balance(
|
||||
&self,
|
||||
address: &AccountId,
|
||||
denom: Denom,
|
||||
denom: String,
|
||||
) -> Result<Option<Coin>, NymdError>
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
|
||||
@@ -49,7 +49,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> MultisigSigningClient for NymdClien
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
|
||||
let release_funds_req = CoconutBandwidthExecuteMsg::ReleaseFunds {
|
||||
funds: Coin::new(voucher_value, DEFAULT_NETWORK.denom()),
|
||||
funds: Coin::new(voucher_value, DEFAULT_NETWORK.mix_denom().base),
|
||||
};
|
||||
let release_funds_msg = CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: self.coconut_bandwidth_contract_address().to_string(),
|
||||
|
||||
@@ -183,6 +183,7 @@ impl<C: CosmWasmClient + Sync + Send> VestingQueryClient for NymdClient<C> {
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
/// Returns the total amount of delegated tokens that have vested
|
||||
async fn delegated_vesting(
|
||||
&self,
|
||||
vesting_account_address: &str,
|
||||
|
||||
@@ -18,12 +18,13 @@ fixed = { version = "1.1", features = ["serde"] }
|
||||
az = "1.1"
|
||||
log = "0.4.14"
|
||||
time = { version = "0.3.6", features = ["parsing", "formatting"] }
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
contracts-common = { path = "../contracts-common" }
|
||||
|
||||
[dev-dependencies]
|
||||
time = { version = "0.3.5", features = ["serde", "macros"] }
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
generate-ts = []
|
||||
|
||||
@@ -33,7 +33,7 @@ pub struct Delegation {
|
||||
pub node_identity: IdentityKey,
|
||||
pub amount: Coin,
|
||||
pub block_height: u64,
|
||||
pub proxy: Option<Addr>, // proxy address used to delegate the funds on behalf of anouther address
|
||||
pub proxy: Option<Addr>, // proxy address used to delegate the funds on behalf of another address
|
||||
}
|
||||
|
||||
impl Eq for Delegation {}
|
||||
|
||||
@@ -8,11 +8,6 @@ use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(export, export_to = "../../../nym-wallet/src/types/rust/gateway.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema)]
|
||||
pub struct Gateway {
|
||||
pub host: String,
|
||||
|
||||
@@ -14,13 +14,10 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(
|
||||
export,
|
||||
export_to = "../../../nym-wallet/src/types/rust/rewardedsetnodestatus.ts"
|
||||
)
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/RewardedSetNodeStatus.ts")
|
||||
)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, JsonSchema, PartialEq)]
|
||||
pub enum RewardedSetNodeStatus {
|
||||
@@ -40,6 +37,16 @@ pub enum DelegationEvent {
|
||||
Undelegate(PendingUndelegate),
|
||||
}
|
||||
|
||||
impl DelegationEvent {
|
||||
pub fn delegation_amount(&self) -> Option<Coin> {
|
||||
match self {
|
||||
DelegationEvent::Delegate(delegation) => Some(delegation.amount.clone()),
|
||||
// I think it would be nice to also expose an amount here to know how much we're undelegating
|
||||
DelegationEvent::Undelegate(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
|
||||
pub struct PendingUndelegate {
|
||||
mix_identity: IdentityKey,
|
||||
@@ -109,11 +116,6 @@ impl PendingUndelegate {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(export, export_to = "../../../nym-wallet/src/types/rust/mixnode.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema)]
|
||||
pub struct MixNode {
|
||||
pub host: String,
|
||||
|
||||
@@ -12,6 +12,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
schemars = "0.8"
|
||||
cw-storage-plus = "0.13.4"
|
||||
config = { path = "../../config" }
|
||||
|
||||
[dev-dependencies]
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
[features]
|
||||
generate-ts = []
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{Coin, Timestamp};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -11,13 +11,13 @@ pub mod events;
|
||||
pub mod messages;
|
||||
|
||||
pub fn one_ucoin() -> Coin {
|
||||
Coin::new(1, DENOM)
|
||||
Coin::new(1, MIX_DENOM.base)
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(export, export_to = "../../../nym-wallet/src/types/rust/period.ts")
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Period.ts")
|
||||
)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, JsonSchema)]
|
||||
pub enum Period {
|
||||
@@ -28,8 +28,8 @@ pub enum Period {
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub struct PledgeData {
|
||||
amount: Coin,
|
||||
block_time: Timestamp,
|
||||
pub amount: Coin,
|
||||
pub block_time: Timestamp,
|
||||
}
|
||||
|
||||
impl PledgeData {
|
||||
@@ -48,9 +48,9 @@ impl PledgeData {
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub struct OriginalVestingResponse {
|
||||
amount: Coin,
|
||||
number_of_periods: usize,
|
||||
period_duration: u64,
|
||||
pub amount: Coin,
|
||||
pub number_of_periods: usize,
|
||||
pub period_duration: u64,
|
||||
}
|
||||
|
||||
impl OriginalVestingResponse {
|
||||
|
||||
@@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fmt, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
DefaultNetworkDetails, ValidatorDetails, MAINNET_DEFAULTS, QA_DEFAULTS, SANDBOX_DEFAULTS,
|
||||
DefaultNetworkDetails, DenomDetails, DenomDetailsOwned, ValidatorDetails, MAINNET_DEFAULTS,
|
||||
QA_DEFAULTS, SANDBOX_DEFAULTS,
|
||||
};
|
||||
|
||||
use thiserror::Error;
|
||||
@@ -24,7 +25,7 @@ pub enum Network {
|
||||
}
|
||||
|
||||
impl Network {
|
||||
fn details(&self) -> &DefaultNetworkDetails<'_> {
|
||||
fn details(&self) -> &DefaultNetworkDetails {
|
||||
match self {
|
||||
Self::QA => &QA_DEFAULTS,
|
||||
Self::SANDBOX => &SANDBOX_DEFAULTS,
|
||||
@@ -36,8 +37,12 @@ impl Network {
|
||||
self.details().bech32_prefix
|
||||
}
|
||||
|
||||
pub fn denom(&self) -> &str {
|
||||
self.details().denom
|
||||
pub fn mix_denom(&self) -> &DenomDetails {
|
||||
&self.details().mix_denom
|
||||
}
|
||||
|
||||
pub fn stake_denom(&self) -> &DenomDetails {
|
||||
&self.details().stake_denom
|
||||
}
|
||||
|
||||
pub fn mixnet_contract_address(&self) -> &str {
|
||||
@@ -97,18 +102,20 @@ impl fmt::Display for Network {
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct NetworkDetails {
|
||||
bech32_prefix: String,
|
||||
denom: String,
|
||||
mix_denom: DenomDetailsOwned,
|
||||
stake_denom: DenomDetailsOwned,
|
||||
mixnet_contract_address: String,
|
||||
vesting_contract_address: String,
|
||||
bandwidth_claim_contract_address: String,
|
||||
validators: Vec<ValidatorDetails>,
|
||||
}
|
||||
|
||||
impl From<&DefaultNetworkDetails<'_>> for NetworkDetails {
|
||||
fn from(details: &DefaultNetworkDetails<'_>) -> Self {
|
||||
impl From<&DefaultNetworkDetails> for NetworkDetails {
|
||||
fn from(details: &DefaultNetworkDetails) -> Self {
|
||||
NetworkDetails {
|
||||
bech32_prefix: details.bech32_prefix.into(),
|
||||
denom: details.denom.into(),
|
||||
mix_denom: details.mix_denom.into(),
|
||||
stake_denom: details.stake_denom.into(),
|
||||
mixnet_contract_address: details.mixnet_contract_address.into(),
|
||||
vesting_contract_address: details.vesting_contract_address.into(),
|
||||
bandwidth_claim_contract_address: details.bandwidth_claim_contract_address.into(),
|
||||
@@ -117,6 +124,12 @@ impl From<&DefaultNetworkDetails<'_>> for NetworkDetails {
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkDetails {
|
||||
pub fn base_mix_denom(&self) -> &str {
|
||||
&self.mix_denom.base
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct SupportedNetworks {
|
||||
networks: HashMap<Network, NetworkDetails>,
|
||||
@@ -141,7 +154,7 @@ impl SupportedNetworks {
|
||||
pub fn denom(&self, network: Network) -> Option<&str> {
|
||||
self.networks
|
||||
.get(&network)
|
||||
.map(|network_details| network_details.denom.as_str())
|
||||
.map(|network_details| network_details.base_mix_denom())
|
||||
}
|
||||
|
||||
pub fn mixnet_contract_address(&self, network: Network) -> Option<&str> {
|
||||
|
||||
@@ -17,24 +17,24 @@ pub mod sandbox;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(network = "mainnet")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::MAINNET;
|
||||
pub const DENOM: &str = mainnet::DENOM;
|
||||
pub const STAKE_DENOM: &str = mainnet::STAKE_DENOM;
|
||||
pub const MIX_DENOM: DenomDetails = mainnet::MIX_DENOM;
|
||||
pub const STAKE_DENOM: DenomDetails = mainnet::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_CONTRACT_ADDRESS;
|
||||
pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = mainnet::_ETH_ERC20_CONTRACT_ADDRESS;
|
||||
|
||||
} else if #[cfg(network = "qa")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::QA;
|
||||
pub const DENOM: &str = qa::DENOM;
|
||||
pub const STAKE_DENOM: &str = qa::STAKE_DENOM;
|
||||
pub const MIX_DENOM: DenomDetails = qa::MIX_DENOM;
|
||||
pub const STAKE_DENOM: DenomDetails = qa::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_CONTRACT_ADDRESS;
|
||||
pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = qa::_ETH_ERC20_CONTRACT_ADDRESS;
|
||||
|
||||
} else if #[cfg(network = "sandbox")] {
|
||||
pub const DEFAULT_NETWORK: all::Network = all::Network::SANDBOX;
|
||||
pub const DENOM: &str = sandbox::DENOM;
|
||||
pub const STAKE_DENOM: &str = sandbox::STAKE_DENOM;
|
||||
pub const MIX_DENOM: DenomDetails = sandbox::MIX_DENOM;
|
||||
pub const STAKE_DENOM: DenomDetails = sandbox::STAKE_DENOM;
|
||||
|
||||
pub const ETH_CONTRACT_ADDRESS: [u8; 20] = sandbox::_ETH_CONTRACT_ADDRESS;
|
||||
pub const ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = sandbox::_ETH_ERC20_CONTRACT_ADDRESS;
|
||||
@@ -45,47 +45,49 @@ cfg_if::cfg_if! {
|
||||
// future. If we do this, and also get rid of the references we could potentially unify with
|
||||
// `NetworkDetails`.
|
||||
#[derive(Debug)]
|
||||
pub struct DefaultNetworkDetails<'a> {
|
||||
bech32_prefix: &'a str,
|
||||
denom: &'a str,
|
||||
mixnet_contract_address: &'a str,
|
||||
vesting_contract_address: &'a str,
|
||||
bandwidth_claim_contract_address: &'a str,
|
||||
coconut_bandwidth_contract_address: &'a str,
|
||||
multisig_contract_address: &'a str,
|
||||
rewarding_validator_address: &'a str,
|
||||
pub struct DefaultNetworkDetails {
|
||||
bech32_prefix: &'static str,
|
||||
mix_denom: DenomDetails,
|
||||
stake_denom: DenomDetails,
|
||||
mixnet_contract_address: &'static str,
|
||||
vesting_contract_address: &'static str,
|
||||
bandwidth_claim_contract_address: &'static str,
|
||||
coconut_bandwidth_contract_address: &'static str,
|
||||
multisig_contract_address: &'static str,
|
||||
rewarding_validator_address: &'static str,
|
||||
validators: Vec<ValidatorDetails>,
|
||||
}
|
||||
|
||||
static MAINNET_DEFAULTS: Lazy<DefaultNetworkDetails<'static>> =
|
||||
Lazy::new(|| DefaultNetworkDetails {
|
||||
bech32_prefix: mainnet::BECH32_PREFIX,
|
||||
denom: mainnet::DENOM,
|
||||
mixnet_contract_address: mainnet::MIXNET_CONTRACT_ADDRESS,
|
||||
vesting_contract_address: mainnet::VESTING_CONTRACT_ADDRESS,
|
||||
bandwidth_claim_contract_address: mainnet::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
coconut_bandwidth_contract_address: mainnet::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
|
||||
multisig_contract_address: mainnet::MULTISIG_CONTRACT_ADDRESS,
|
||||
rewarding_validator_address: mainnet::REWARDING_VALIDATOR_ADDRESS,
|
||||
validators: mainnet::validators(),
|
||||
});
|
||||
static MAINNET_DEFAULTS: Lazy<DefaultNetworkDetails> = Lazy::new(|| DefaultNetworkDetails {
|
||||
bech32_prefix: mainnet::BECH32_PREFIX,
|
||||
mix_denom: mainnet::MIX_DENOM,
|
||||
stake_denom: mainnet::STAKE_DENOM,
|
||||
mixnet_contract_address: mainnet::MIXNET_CONTRACT_ADDRESS,
|
||||
vesting_contract_address: mainnet::VESTING_CONTRACT_ADDRESS,
|
||||
bandwidth_claim_contract_address: mainnet::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
coconut_bandwidth_contract_address: mainnet::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
|
||||
multisig_contract_address: mainnet::MULTISIG_CONTRACT_ADDRESS,
|
||||
rewarding_validator_address: mainnet::REWARDING_VALIDATOR_ADDRESS,
|
||||
validators: mainnet::validators(),
|
||||
});
|
||||
|
||||
static SANDBOX_DEFAULTS: Lazy<DefaultNetworkDetails<'static>> =
|
||||
Lazy::new(|| DefaultNetworkDetails {
|
||||
bech32_prefix: sandbox::BECH32_PREFIX,
|
||||
denom: sandbox::DENOM,
|
||||
mixnet_contract_address: sandbox::MIXNET_CONTRACT_ADDRESS,
|
||||
vesting_contract_address: sandbox::VESTING_CONTRACT_ADDRESS,
|
||||
bandwidth_claim_contract_address: sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
coconut_bandwidth_contract_address: sandbox::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
|
||||
multisig_contract_address: sandbox::MULTISIG_CONTRACT_ADDRESS,
|
||||
rewarding_validator_address: sandbox::REWARDING_VALIDATOR_ADDRESS,
|
||||
validators: sandbox::validators(),
|
||||
});
|
||||
static SANDBOX_DEFAULTS: Lazy<DefaultNetworkDetails> = Lazy::new(|| DefaultNetworkDetails {
|
||||
bech32_prefix: sandbox::BECH32_PREFIX,
|
||||
mix_denom: sandbox::MIX_DENOM,
|
||||
stake_denom: sandbox::STAKE_DENOM,
|
||||
mixnet_contract_address: sandbox::MIXNET_CONTRACT_ADDRESS,
|
||||
vesting_contract_address: sandbox::VESTING_CONTRACT_ADDRESS,
|
||||
bandwidth_claim_contract_address: sandbox::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
coconut_bandwidth_contract_address: sandbox::COCONUT_BANDWIDTH_CONTRACT_ADDRESS,
|
||||
multisig_contract_address: sandbox::MULTISIG_CONTRACT_ADDRESS,
|
||||
rewarding_validator_address: sandbox::REWARDING_VALIDATOR_ADDRESS,
|
||||
validators: sandbox::validators(),
|
||||
});
|
||||
|
||||
static QA_DEFAULTS: Lazy<DefaultNetworkDetails<'static>> = Lazy::new(|| DefaultNetworkDetails {
|
||||
static QA_DEFAULTS: Lazy<DefaultNetworkDetails> = Lazy::new(|| DefaultNetworkDetails {
|
||||
bech32_prefix: qa::BECH32_PREFIX,
|
||||
denom: qa::DENOM,
|
||||
mix_denom: qa::MIX_DENOM,
|
||||
stake_denom: qa::STAKE_DENOM,
|
||||
mixnet_contract_address: qa::MIXNET_CONTRACT_ADDRESS,
|
||||
vesting_contract_address: qa::VESTING_CONTRACT_ADDRESS,
|
||||
bandwidth_claim_contract_address: qa::BANDWIDTH_CLAIM_CONTRACT_ADDRESS,
|
||||
@@ -95,6 +97,42 @@ static QA_DEFAULTS: Lazy<DefaultNetworkDetails<'static>> = Lazy::new(|| DefaultN
|
||||
validators: qa::validators(),
|
||||
});
|
||||
|
||||
#[derive(Debug, Copy, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct DenomDetails {
|
||||
pub base: &'static str,
|
||||
pub display: &'static str,
|
||||
// i.e. display_amount * 10^display_exponent = base_amount
|
||||
pub display_exponent: u32,
|
||||
}
|
||||
|
||||
impl DenomDetails {
|
||||
pub const fn new(base: &'static str, display: &'static str, display_exponent: u32) -> Self {
|
||||
DenomDetails {
|
||||
base,
|
||||
display,
|
||||
display_exponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct DenomDetailsOwned {
|
||||
pub base: String,
|
||||
pub display: String,
|
||||
// i.e. display_amount * 10^display_exponent = base_amount
|
||||
pub display_exponent: u32,
|
||||
}
|
||||
|
||||
impl From<DenomDetails> for DenomDetailsOwned {
|
||||
fn from(details: DenomDetails) -> Self {
|
||||
DenomDetailsOwned {
|
||||
base: details.base.to_owned(),
|
||||
display: details.display.to_owned(),
|
||||
display_exponent: details.display_exponent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct ValidatorDetails {
|
||||
// it is assumed those values are always valid since they're being provided in our defaults file
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::ValidatorDetails;
|
||||
use crate::{DenomDetails, ValidatorDetails};
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "n";
|
||||
pub const DENOM: &str = "unym";
|
||||
pub const STAKE_DENOM: &str = "unyx";
|
||||
|
||||
pub const MIX_DENOM: DenomDetails = DenomDetails::new("unym", "nym", 6);
|
||||
pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6);
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str =
|
||||
"n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g";
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::ValidatorDetails;
|
||||
use crate::{DenomDetails, ValidatorDetails};
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "n";
|
||||
pub const DENOM: &str = "unym";
|
||||
pub const STAKE_DENOM: &str = "unyx";
|
||||
|
||||
pub const MIX_DENOM: DenomDetails = DenomDetails::new("unym", "nym", 6);
|
||||
pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6);
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str =
|
||||
"n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep";
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::ValidatorDetails;
|
||||
use crate::{DenomDetails, ValidatorDetails};
|
||||
|
||||
pub(crate) const BECH32_PREFIX: &str = "nymt";
|
||||
pub const DENOM: &str = "unymt";
|
||||
pub const STAKE_DENOM: &str = "unyxt";
|
||||
|
||||
pub const MIX_DENOM: DenomDetails = DenomDetails::new("unymt", "nymt", 6);
|
||||
pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyxt", "nyxt", 6);
|
||||
|
||||
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str = "nymt1ghd753shjuwexxywmgs4xz7x2q732vcnstz02j";
|
||||
pub(crate) const VESTING_CONTRACT_ADDRESS: &str = "nymt14ejqjyq8um4p3xfqj74yld5waqljf88fn549lh";
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
[package]
|
||||
name = "nym-types"
|
||||
version = "1.0.0"
|
||||
description = "Nym common types"
|
||||
authors = ["Nym Technologies SA"]
|
||||
edition = "2021"
|
||||
rust-version = "1.58"
|
||||
|
||||
[dependencies]
|
||||
eyre = "0.6.5"
|
||||
log = "0.4"
|
||||
itertools = "0.10"
|
||||
reqwest = "0.11.9"
|
||||
schemars = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
url = "2.2"
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmrs = "0.7.0"
|
||||
|
||||
validator-client = { path = "../../common/client-libs/validator-client", features = [
|
||||
"nymd-client",
|
||||
] }
|
||||
mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
config = { path = "../../common/config" }
|
||||
coconut-interface = { path = "../../common/coconut-interface" }
|
||||
# Used for Type conversion, can be extracted but its a lot of work
|
||||
vesting-contract = { path = "../../contracts/vesting" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.3.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
generate-ts = []
|
||||
@@ -0,0 +1,70 @@
|
||||
use crate::currency::{DecCoin, Denom};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Account.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, JsonSchema)]
|
||||
pub struct Account {
|
||||
// TODO: discuss with @MS whether it makes sense:
|
||||
// 1. why are we restricting to single denom here? What if user holds both stake and mix currencies?
|
||||
// 2. what's the `contract_address`? is it mixnet? vesting? coconut? why does it relate to an account anyway?
|
||||
pub contract_address: String,
|
||||
pub client_address: String,
|
||||
pub denom: Denom,
|
||||
}
|
||||
|
||||
impl Account {
|
||||
pub fn new(contract_address: String, client_address: String, denom: Denom) -> Self {
|
||||
Account {
|
||||
contract_address,
|
||||
client_address,
|
||||
denom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/AccountWithMnemonic.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AccountWithMnemonic {
|
||||
pub account: Account,
|
||||
pub mnemonic: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/AccountEntry.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AccountEntry {
|
||||
pub id: String,
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Balance.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Balance {
|
||||
pub amount: DecCoin,
|
||||
pub printable_balance: String,
|
||||
}
|
||||
|
||||
impl Balance {
|
||||
pub fn new(amount: DecCoin) -> Self {
|
||||
Balance {
|
||||
printable_balance: amount.to_string(),
|
||||
amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
use crate::error::TypesError;
|
||||
use config::defaults::all::Network;
|
||||
use config::defaults::DenomDetails;
|
||||
use cosmwasm_std::Fraction;
|
||||
use cosmwasm_std::{Decimal, Uint128};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use strum::{Display, EnumString, EnumVariantNames};
|
||||
use validator_client::nymd::Coin;
|
||||
|
||||
#[cfg(feature = "generate-ts")]
|
||||
use ts_rs::{Dependency, TS};
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/CurrencyDenom.ts")
|
||||
)]
|
||||
#[cfg_attr(feature = "generate-ts", ts(rename_all = "lowercase"))]
|
||||
#[derive(
|
||||
Display,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Clone,
|
||||
Debug,
|
||||
EnumString,
|
||||
EnumVariantNames,
|
||||
PartialEq,
|
||||
JsonSchema,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum CurrencyDenom {
|
||||
#[strum(ascii_case_insensitive)]
|
||||
Nym,
|
||||
#[strum(ascii_case_insensitive)]
|
||||
Nymt,
|
||||
#[strum(ascii_case_insensitive)]
|
||||
Nyx,
|
||||
#[strum(ascii_case_insensitive)]
|
||||
Nyxt,
|
||||
}
|
||||
|
||||
pub type Denom = String;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct RegisteredCoins(HashMap<Denom, CoinMetadata>);
|
||||
|
||||
impl RegisteredCoins {
|
||||
pub fn default_denoms(network: Network) -> Self {
|
||||
let mut network_coins = HashMap::new();
|
||||
network_coins.insert(
|
||||
network.mix_denom().base.into(),
|
||||
(*network.mix_denom()).into(),
|
||||
);
|
||||
network_coins.insert(
|
||||
network.stake_denom().base.into(),
|
||||
(*network.stake_denom()).into(),
|
||||
);
|
||||
RegisteredCoins(network_coins)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, denom: Denom, metadata: CoinMetadata) -> Option<CoinMetadata> {
|
||||
self.0.insert(denom, metadata)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, denom: &Denom) -> Option<CoinMetadata> {
|
||||
self.0.remove(denom)
|
||||
}
|
||||
|
||||
pub fn attempt_convert_to_base_coin(&self, coin: DecCoin) -> Result<Coin, TypesError> {
|
||||
// check if this is already in the base denom
|
||||
if self.0.contains_key(&coin.denom) {
|
||||
// if we're converting a base DecCoin it CANNOT fail, unless somebody is providing
|
||||
// bullshit data on purpose : )
|
||||
return coin.try_into();
|
||||
} else {
|
||||
// TODO: this kinda suggests we may need a better data structure
|
||||
for registered_coin in self.0.values() {
|
||||
if let Some(exponent) = registered_coin.get_exponent(&coin.denom) {
|
||||
let amount = try_convert_decimal_to_u128(coin.try_scale_up_value(exponent)?)?;
|
||||
return Ok(Coin::new(amount, ®istered_coin.base));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(TypesError::UnknownCoinDenom(coin.denom))
|
||||
}
|
||||
|
||||
pub fn attempt_convert_to_display_dec_coin(&self, coin: Coin) -> Result<DecCoin, TypesError> {
|
||||
for registered_coin in self.0.values() {
|
||||
if let Some(exponent) = registered_coin.get_exponent(&coin.denom) {
|
||||
// if this fails it means we haven't registered our display denom which honestly should never be the case
|
||||
// unless somebody is rocking their own custom network
|
||||
let display_exponent = registered_coin
|
||||
.get_exponent(®istered_coin.display)
|
||||
.ok_or_else(|| TypesError::UnknownCoinDenom(coin.denom.clone()))?;
|
||||
|
||||
return match exponent.cmp(&display_exponent) {
|
||||
Ordering::Greater => {
|
||||
// we need to scale up, unlikely to ever be needed but included for completion sake,
|
||||
// for example if we decided to created knym with exponent 9 and wanted to convert to nym with exponent 6
|
||||
Ok(DecCoin::new_scaled_up(
|
||||
coin.amount,
|
||||
®istered_coin.display,
|
||||
exponent - display_exponent,
|
||||
)?)
|
||||
}
|
||||
// we're already in the display denom
|
||||
Ordering::Equal => Ok(coin.into()),
|
||||
Ordering::Less => {
|
||||
// we need to scale down, the most common case, for example we're in base unym with exponent 0 and want to convert to nym with exponent 6
|
||||
Ok(DecCoin::new_scaled_down(
|
||||
coin.amount,
|
||||
®istered_coin.display,
|
||||
display_exponent - exponent,
|
||||
)?)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Err(TypesError::UnknownCoinDenom(coin.denom))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: should this live here?
|
||||
// attempts to replicate cosmos-sdk's coin metadata
|
||||
// https://docs.cosmos.network/master/architecture/adr-024-coin-metadata.html
|
||||
// this way we could more easily handle multiple coin types simultaneously (like nym/nyx/nymt/nyx + local currencies)
|
||||
#[derive(Debug)]
|
||||
pub struct DenomUnit {
|
||||
pub denom: Denom,
|
||||
pub exponent: u32,
|
||||
// pub aliases: Vec<String>,
|
||||
}
|
||||
|
||||
impl DenomUnit {
|
||||
pub fn new(denom: Denom, exponent: u32) -> Self {
|
||||
DenomUnit { denom, exponent }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CoinMetadata {
|
||||
pub denom_units: Vec<DenomUnit>,
|
||||
pub base: Denom,
|
||||
pub display: Denom,
|
||||
}
|
||||
|
||||
impl CoinMetadata {
|
||||
pub fn new(denom_units: Vec<DenomUnit>, base: Denom, display: Denom) -> Self {
|
||||
CoinMetadata {
|
||||
denom_units,
|
||||
base,
|
||||
display,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_exponent(&self, denom: &str) -> Option<u32> {
|
||||
self.denom_units
|
||||
.iter()
|
||||
.find(|denom_unit| denom_unit.denom == denom)
|
||||
.map(|denom_unit| denom_unit.exponent)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DenomDetails> for CoinMetadata {
|
||||
fn from(denom_details: DenomDetails) -> Self {
|
||||
CoinMetadata::new(
|
||||
vec![
|
||||
DenomUnit::new(denom_details.base.into(), 0),
|
||||
DenomUnit::new(denom_details.display.into(), denom_details.display_exponent),
|
||||
],
|
||||
denom_details.base.into(),
|
||||
denom_details.display.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// tries to semi-replicate cosmos-sdk's DecCoin for being able to handle tokens with decimal amounts
|
||||
// https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/types/dec_coin.go
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub struct DecCoin {
|
||||
pub denom: Denom,
|
||||
// Decimal is already serialized to string and using string in its schema, so lets also go straight to string for ts_rs
|
||||
// todo: is `Decimal` the correct type to use? Do we want to depend on cosmwasm_std here?
|
||||
pub amount: Decimal,
|
||||
}
|
||||
|
||||
// I had to implement it manually to correctly set dependencies
|
||||
#[cfg(feature = "generate-ts")]
|
||||
impl TS for DecCoin {
|
||||
const EXPORT_TO: Option<&'static str> = Some("ts-packages/types/src/types/rust/DecCoin.ts");
|
||||
|
||||
fn decl() -> String {
|
||||
format!("type {} = {};", Self::name(), Self::inline())
|
||||
}
|
||||
|
||||
fn name() -> String {
|
||||
"DecCoin".into()
|
||||
}
|
||||
|
||||
fn inline() -> String {
|
||||
"{ denom: CurrencyDenom, amount: string }".into()
|
||||
}
|
||||
|
||||
fn dependencies() -> Vec<Dependency> {
|
||||
vec![Dependency::from_ty::<CurrencyDenom>()
|
||||
.expect("TS was incorrectly defined on `CurrencyDenom`")]
|
||||
}
|
||||
|
||||
fn transparent() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl DecCoin {
|
||||
pub fn new_base<S: Into<String>>(amount: impl Into<Uint128>, denom: S) -> Self {
|
||||
DecCoin {
|
||||
denom: denom.into(),
|
||||
amount: Decimal::from_atomics(amount, 0).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn zero<S: Into<String>>(denom: S) -> Self {
|
||||
DecCoin {
|
||||
denom: denom.into(),
|
||||
amount: Decimal::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_scaled_up<S: Into<String>>(
|
||||
base_amount: impl Into<Uint128>,
|
||||
denom: S,
|
||||
exponent: u32,
|
||||
) -> Result<Self, TypesError> {
|
||||
let base_amount = Decimal::from_atomics(base_amount, 0).unwrap();
|
||||
Ok(DecCoin {
|
||||
denom: denom.into(),
|
||||
amount: try_scale_up_decimal(base_amount, exponent)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_scaled_down<S: Into<String>>(
|
||||
base_amount: impl Into<Uint128>,
|
||||
denom: S,
|
||||
exponent: u32,
|
||||
) -> Result<Self, TypesError> {
|
||||
let base_amount = Decimal::from_atomics(base_amount, 0).unwrap();
|
||||
Ok(DecCoin {
|
||||
denom: denom.into(),
|
||||
amount: try_scale_down_decimal(base_amount, exponent)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_scale_down_value(&self, exponent: u32) -> Result<Decimal, TypesError> {
|
||||
try_scale_down_decimal(self.amount, exponent)
|
||||
}
|
||||
|
||||
pub fn try_scale_up_value(&self, exponent: u32) -> Result<Decimal, TypesError> {
|
||||
try_scale_up_decimal(self.amount, exponent)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: should thoese live here?
|
||||
pub fn try_scale_down_decimal(dec: Decimal, exponent: u32) -> Result<Decimal, TypesError> {
|
||||
let rhs = 10u128
|
||||
.checked_pow(exponent)
|
||||
.ok_or(TypesError::UnsupportedExponent(exponent))?;
|
||||
let denominator = dec
|
||||
.denominator()
|
||||
.checked_mul(rhs.into())
|
||||
.map_err(|_| TypesError::UnsupportedExponent(exponent))?;
|
||||
|
||||
Ok(Decimal::from_ratio(dec.numerator(), denominator))
|
||||
}
|
||||
|
||||
pub fn try_scale_up_decimal(dec: Decimal, exponent: u32) -> Result<Decimal, TypesError> {
|
||||
let rhs = 10u128
|
||||
.checked_pow(exponent)
|
||||
.ok_or(TypesError::UnsupportedExponent(exponent))?;
|
||||
let denominator = dec
|
||||
.denominator()
|
||||
.checked_div(rhs.into())
|
||||
.map_err(|_| TypesError::UnsupportedExponent(exponent))?;
|
||||
|
||||
Ok(Decimal::from_ratio(dec.numerator(), denominator))
|
||||
}
|
||||
|
||||
pub fn try_convert_decimal_to_u128(dec: Decimal) -> Result<u128, TypesError> {
|
||||
let whole = dec.numerator() / dec.denominator();
|
||||
|
||||
// unwrap is fine as we're not dividing by zero here
|
||||
let fractional = (dec.numerator()).checked_rem(dec.denominator()).unwrap();
|
||||
|
||||
// we cannot convert as we'd lose our decimal places
|
||||
// (for example if somebody attempted to represent our gas price (WHICH YOU SHOULDN'T DO) as DecCoin)
|
||||
if fractional != Uint128::zero() {
|
||||
return Err(TypesError::LossyCoinConversion);
|
||||
}
|
||||
Ok(whole.u128())
|
||||
}
|
||||
|
||||
// TODO: adjust the implementation to as required by @MS or @FT
|
||||
impl Display for DecCoin {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}{}", self.amount, self.denom)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Coin> for DecCoin {
|
||||
fn from(coin: Coin) -> Self {
|
||||
DecCoin::new_base(coin.amount, coin.denom)
|
||||
}
|
||||
}
|
||||
|
||||
// this conversion assumes same denomination
|
||||
impl TryFrom<DecCoin> for Coin {
|
||||
type Error = TypesError;
|
||||
|
||||
fn try_from(value: DecCoin) -> Result<Self, Self::Error> {
|
||||
Ok(Coin {
|
||||
amount: try_convert_decimal_to_u128(value.try_scale_down_value(0)?)?,
|
||||
denom: value.denom,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use std::convert::TryFrom;
|
||||
use std::string::ToString;
|
||||
|
||||
#[test]
|
||||
fn dec_value_scale_down() {
|
||||
let dec = DecCoin {
|
||||
denom: "foo".to_string(),
|
||||
amount: "1234007000".parse().unwrap(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
"1234007000".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(0).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"123400700".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(1).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"12340070".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(2).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"123400.7".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(4).unwrap()
|
||||
);
|
||||
|
||||
let dec = DecCoin {
|
||||
denom: "foo".to_string(),
|
||||
amount: "10000000000".parse().unwrap(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
"100".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(8).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"1".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(10).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"0.01".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_down_value(12).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dec_value_scale_up() {
|
||||
let dec = DecCoin {
|
||||
denom: "foo".to_string(),
|
||||
amount: "1234.56".parse().unwrap(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
"1234.56".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(0).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"12345.6".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(1).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"123456".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(2).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"1234560".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(3).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"12345600".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(4).unwrap()
|
||||
);
|
||||
|
||||
let dec = DecCoin {
|
||||
denom: "foo".to_string(),
|
||||
amount: "0.00000123".parse().unwrap(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
"0.0000123".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(1).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"0.000123".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(2).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"123".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(8).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"1230".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(9).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
"12300".parse::<Decimal>().unwrap(),
|
||||
dec.try_scale_up_value(10).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coin_to_dec_coin() {
|
||||
let coin = Coin::new(123, "foo");
|
||||
let dec = DecCoin::from(coin.clone());
|
||||
assert_eq!(coin.denom, dec.denom);
|
||||
assert_eq!(dec.amount, Decimal::from_atomics(coin.amount, 0).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dec_coin_to_coin() {
|
||||
let dec = DecCoin {
|
||||
denom: "foo".to_string(),
|
||||
amount: "123".parse().unwrap(),
|
||||
};
|
||||
let coin = Coin::try_from(dec.clone()).unwrap();
|
||||
assert_eq!(dec.denom, coin.denom);
|
||||
assert_eq!(coin.amount, 123u128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn converting_to_display() {
|
||||
let reg = RegisteredCoins::default_denoms(Network::MAINNET);
|
||||
let values = vec![
|
||||
(1u128, "0.000001"),
|
||||
(10u128, "0.00001"),
|
||||
(100u128, "0.0001"),
|
||||
(1000u128, "0.001"),
|
||||
(10000u128, "0.01"),
|
||||
(100000u128, "0.1"),
|
||||
(1000000u128, "1"),
|
||||
(1234567u128, "1.234567"),
|
||||
(123456700u128, "123.4567"),
|
||||
];
|
||||
|
||||
for (raw, expected) in values {
|
||||
let coin = Coin::new(raw, Network::MAINNET.mix_denom().base);
|
||||
let display = reg.attempt_convert_to_display_dec_coin(coin).unwrap();
|
||||
assert_eq!(Network::MAINNET.mix_denom().display, display.denom);
|
||||
assert_eq!(expected, display.amount.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn converting_to_base() {
|
||||
let reg = RegisteredCoins::default_denoms(Network::MAINNET);
|
||||
let values = vec![
|
||||
(1u128, "0.000001"),
|
||||
(10u128, "0.00001"),
|
||||
(100u128, "0.0001"),
|
||||
(1000u128, "0.001"),
|
||||
(10000u128, "0.01"),
|
||||
(100000u128, "0.1"),
|
||||
(1000000u128, "1"),
|
||||
(1234567u128, "1.234567"),
|
||||
(123456700u128, "123.4567"),
|
||||
];
|
||||
|
||||
for (expected, raw_display) in values {
|
||||
let coin = DecCoin {
|
||||
denom: Network::MAINNET.mix_denom().display.into(),
|
||||
amount: raw_display.parse().unwrap(),
|
||||
};
|
||||
let base = reg.attempt_convert_to_base_coin(coin).unwrap();
|
||||
assert_eq!(Network::MAINNET.mix_denom().base, base.denom);
|
||||
assert_eq!(expected, base.amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
use crate::currency::{DecCoin, RegisteredCoins};
|
||||
use crate::error::TypesError;
|
||||
use mixnet_contract_common::mixnode::DelegationEvent as ContractDelegationEvent;
|
||||
use mixnet_contract_common::mixnode::PendingUndelegate as ContractPendingUndelegate;
|
||||
use mixnet_contract_common::Delegation as MixnetContractDelegation;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Delegation.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
pub struct Delegation {
|
||||
pub owner: String,
|
||||
pub node_identity: String,
|
||||
pub amount: DecCoin,
|
||||
pub block_height: u64,
|
||||
pub proxy: Option<String>, // proxy address used to delegate the funds on behalf of another address
|
||||
}
|
||||
|
||||
impl Delegation {
|
||||
pub fn from_mixnet_contract(
|
||||
delegation: MixnetContractDelegation,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(Delegation {
|
||||
owner: delegation.owner.to_string(),
|
||||
node_identity: delegation.node_identity,
|
||||
amount: reg.attempt_convert_to_display_dec_coin(delegation.amount.into())?,
|
||||
block_height: delegation.block_height,
|
||||
proxy: delegation.proxy.map(|d| d.to_string()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/DelegationRecord.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
pub struct DelegationRecord {
|
||||
pub amount: DecCoin,
|
||||
pub block_height: u64,
|
||||
pub delegated_on_iso_datetime: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/DelegationWithEverything.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
pub struct DelegationWithEverything {
|
||||
pub owner: String,
|
||||
pub node_identity: String,
|
||||
pub amount: DecCoin,
|
||||
pub total_delegation: Option<DecCoin>,
|
||||
pub pledge_amount: Option<DecCoin>,
|
||||
pub block_height: u64,
|
||||
pub delegated_on_iso_datetime: String,
|
||||
pub profit_margin_percent: Option<u8>,
|
||||
pub avg_uptime_percent: Option<u8>,
|
||||
pub stake_saturation: Option<f32>,
|
||||
pub proxy: Option<String>,
|
||||
pub accumulated_rewards: Option<DecCoin>,
|
||||
pub pending_events: Vec<DelegationEvent>,
|
||||
pub history: Vec<DelegationRecord>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/DelegationResult.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, JsonSchema, Clone, PartialEq, Debug)]
|
||||
pub struct DelegationResult {
|
||||
source_address: String,
|
||||
target_address: String,
|
||||
amount: Option<DecCoin>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/DelegationEventKind.ts")
|
||||
)]
|
||||
#[derive(Clone, Deserialize, Serialize, PartialEq, JsonSchema, Debug)]
|
||||
pub enum DelegationEventKind {
|
||||
Delegate,
|
||||
Undelegate,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/DelegationEvent.ts")
|
||||
)]
|
||||
#[derive(Clone, Deserialize, Serialize, PartialEq, JsonSchema, Debug)]
|
||||
pub struct DelegationEvent {
|
||||
pub kind: DelegationEventKind,
|
||||
pub node_identity: String,
|
||||
pub address: String,
|
||||
pub amount: Option<DecCoin>,
|
||||
pub block_height: u64,
|
||||
}
|
||||
|
||||
impl DelegationEvent {
|
||||
pub fn from_mixnet_contract(
|
||||
event: ContractDelegationEvent,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(match event {
|
||||
ContractDelegationEvent::Delegate(delegation) => DelegationEvent {
|
||||
kind: DelegationEventKind::Delegate,
|
||||
block_height: delegation.block_height,
|
||||
address: delegation.owner.into_string(),
|
||||
node_identity: delegation.node_identity,
|
||||
amount: Some(reg.attempt_convert_to_display_dec_coin(delegation.amount.into())?),
|
||||
},
|
||||
ContractDelegationEvent::Undelegate(pending_undelegate) => DelegationEvent {
|
||||
kind: DelegationEventKind::Undelegate,
|
||||
block_height: pending_undelegate.block_height(),
|
||||
address: pending_undelegate.delegate().into_string(),
|
||||
node_identity: pending_undelegate.mix_identity(),
|
||||
amount: None,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/PendingUndelegate.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize, PartialEq, JsonSchema, Clone, Debug)]
|
||||
pub struct PendingUndelegate {
|
||||
mix_identity: String,
|
||||
delegate: String,
|
||||
proxy: Option<String>,
|
||||
block_height: u64,
|
||||
}
|
||||
|
||||
impl From<ContractPendingUndelegate> for PendingUndelegate {
|
||||
fn from(pending_undelegate: ContractPendingUndelegate) -> Self {
|
||||
PendingUndelegate {
|
||||
mix_identity: pending_undelegate.mix_identity(),
|
||||
delegate: pending_undelegate.delegate().to_string(),
|
||||
proxy: pending_undelegate.proxy().map(|p| p.to_string()),
|
||||
block_height: pending_undelegate.block_height(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/DelegationSummaryResponse.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct DelegationsSummaryResponse {
|
||||
pub delegations: Vec<DelegationWithEverything>,
|
||||
pub total_delegations: DecCoin,
|
||||
pub total_rewards: DecCoin,
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
use serde::{Serialize, Serializer};
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
use validator_client::validator_api::error::ValidatorAPIError;
|
||||
use validator_client::{nymd::error::NymdError, ValidatorClientError};
|
||||
|
||||
// TODO: ask @MS why this even exists
|
||||
#[derive(Error, Debug)]
|
||||
pub enum TypesError {
|
||||
#[error("{source}")]
|
||||
NymdError {
|
||||
#[from]
|
||||
source: NymdError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
CosmwasmStd {
|
||||
#[from]
|
||||
source: cosmwasm_std::StdError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ErrorReport {
|
||||
#[from]
|
||||
source: eyre::Report,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ValidatorApiError {
|
||||
#[from]
|
||||
source: ValidatorAPIError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
IOError {
|
||||
#[from]
|
||||
source: io::Error,
|
||||
},
|
||||
#[error("{source}")]
|
||||
SerdeJsonError {
|
||||
#[from]
|
||||
source: serde_json::Error,
|
||||
},
|
||||
#[error("{source}")]
|
||||
MalformedUrlProvided {
|
||||
#[from]
|
||||
source: url::ParseError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ReqwestError {
|
||||
#[from]
|
||||
source: reqwest::Error,
|
||||
},
|
||||
#[error("{source}")]
|
||||
DecimalRangeExceeded {
|
||||
#[from]
|
||||
source: cosmwasm_std::DecimalRangeExceeded,
|
||||
},
|
||||
#[error("{0} is not a valid amount string")]
|
||||
InvalidAmount(String),
|
||||
#[error("{0} is not a valid denomination string")]
|
||||
InvalidDenom(String),
|
||||
#[error("Mixnode not found")]
|
||||
MixnodeNotFound(),
|
||||
#[error("Gateway bond is not valid")]
|
||||
InvalidGatewayBond(),
|
||||
#[error("Invalid delegations")]
|
||||
DelegationsInvalid,
|
||||
#[error("Attempted to use too huge currency exponent ({0})")]
|
||||
UnsupportedExponent(u32),
|
||||
#[error("Attempted to convert coin that would have resulted in loss of precision")]
|
||||
LossyCoinConversion,
|
||||
#[error("The provided coin has an unknown denomination - {0}")]
|
||||
UnknownCoinDenom(String),
|
||||
}
|
||||
|
||||
impl Serialize for TypesError {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.collect_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValidatorClientError> for TypesError {
|
||||
fn from(e: ValidatorClientError) -> Self {
|
||||
match e {
|
||||
ValidatorClientError::ValidatorAPIError { source } => source.into(),
|
||||
ValidatorClientError::MalformedUrlProvided(e) => e.into(),
|
||||
ValidatorClientError::NymdError(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::currency::DecCoin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator_client::nymd::Fee;
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/FeeDetails.ts")
|
||||
)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FeeDetails {
|
||||
// expected to be used by the wallet in order to display detailed fee information to the user
|
||||
pub amount: Option<DecCoin>,
|
||||
#[cfg_attr(feature = "generate-ts", ts(skip))]
|
||||
pub fee: Fee,
|
||||
}
|
||||
|
||||
impl FeeDetails {
|
||||
pub fn new(amount: Option<DecCoin>, fee: Fee) -> Self {
|
||||
FeeDetails { amount, fee }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
use cosmrs::tx::Gas as CosmrsGas;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator_client::nymd::cosmwasm_client::types::GasInfo as ValidatorClientGasInfo;
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Gas.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug)]
|
||||
pub struct Gas {
|
||||
/// units of gas used
|
||||
pub gas_units: u64,
|
||||
}
|
||||
|
||||
impl Gas {
|
||||
pub fn from_u64(value: u64) -> Gas {
|
||||
Gas { gas_units: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CosmrsGas> for Gas {
|
||||
fn from(gas: CosmrsGas) -> Self {
|
||||
Gas {
|
||||
gas_units: gas.value(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/GasInfo.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug)]
|
||||
pub struct GasInfo {
|
||||
/// GasWanted is the maximum units of work we allow this tx to perform.
|
||||
pub gas_wanted: Gas,
|
||||
|
||||
/// GasUsed is the amount of gas actually consumed.
|
||||
pub gas_used: Gas,
|
||||
}
|
||||
|
||||
impl From<ValidatorClientGasInfo> for GasInfo {
|
||||
fn from(info: ValidatorClientGasInfo) -> Self {
|
||||
GasInfo {
|
||||
gas_wanted: info.gas_wanted.into(),
|
||||
gas_used: info.gas_used.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GasInfo {
|
||||
pub fn from_u64(gas_wanted: u64, gas_used: u64) -> GasInfo {
|
||||
GasInfo {
|
||||
gas_wanted: Gas::from_u64(gas_wanted),
|
||||
gas_used: Gas::from_u64(gas_used),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
use crate::currency::{DecCoin, RegisteredCoins};
|
||||
use crate::error::TypesError;
|
||||
use mixnet_contract_common::{
|
||||
Gateway as MixnetContractGateway, GatewayBond as MixnetContractGatewayBond,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Gateway.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema)]
|
||||
pub struct Gateway {
|
||||
pub host: String,
|
||||
pub mix_port: u16,
|
||||
pub clients_port: u16,
|
||||
pub location: String,
|
||||
pub sphinx_key: String,
|
||||
/// Base58 encoded ed25519 EdDSA public key of the gateway used to derive shared keys with clients
|
||||
pub identity_key: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
impl From<MixnetContractGateway> for Gateway {
|
||||
fn from(value: MixnetContractGateway) -> Self {
|
||||
let MixnetContractGateway {
|
||||
host,
|
||||
mix_port,
|
||||
clients_port,
|
||||
location,
|
||||
sphinx_key,
|
||||
identity_key,
|
||||
version,
|
||||
} = value;
|
||||
|
||||
Gateway {
|
||||
host,
|
||||
mix_port,
|
||||
clients_port,
|
||||
location,
|
||||
sphinx_key,
|
||||
identity_key,
|
||||
version,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/GatewayBond.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct GatewayBond {
|
||||
pub pledge_amount: DecCoin,
|
||||
pub owner: String,
|
||||
pub block_height: u64,
|
||||
pub gateway: Gateway,
|
||||
pub proxy: Option<String>,
|
||||
}
|
||||
|
||||
impl GatewayBond {
|
||||
pub fn from_mixnet_contract_gateway_bond(
|
||||
bond: MixnetContractGatewayBond,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<GatewayBond, TypesError> {
|
||||
Ok(GatewayBond {
|
||||
pledge_amount: reg.attempt_convert_to_display_dec_coin(bond.pledge_amount.into())?,
|
||||
owner: bond.owner.to_string(),
|
||||
block_height: bond.block_height,
|
||||
gateway: bond.gateway.into(),
|
||||
proxy: bond.proxy.map(|p| p.into_string()),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
pub mod account;
|
||||
pub mod currency;
|
||||
pub mod delegation;
|
||||
pub mod error;
|
||||
pub mod fees;
|
||||
pub mod gas;
|
||||
pub mod gateway;
|
||||
pub mod mixnode;
|
||||
pub mod transaction;
|
||||
pub mod vesting;
|
||||
@@ -0,0 +1,96 @@
|
||||
use crate::currency::{DecCoin, RegisteredCoins};
|
||||
use crate::error::TypesError;
|
||||
use mixnet_contract_common::{
|
||||
MixNode as MixnetContractMixNode, MixNodeBond as MixnetContractMixNodeBond,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator_client::nymd::Coin;
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/Mixnode.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize, JsonSchema)]
|
||||
pub struct MixNode {
|
||||
pub host: String,
|
||||
pub mix_port: u16,
|
||||
pub verloc_port: u16,
|
||||
pub http_api_port: u16,
|
||||
pub sphinx_key: String,
|
||||
/// Base58 encoded ed25519 EdDSA public key.
|
||||
pub identity_key: String,
|
||||
pub version: String,
|
||||
pub profit_margin_percent: u8,
|
||||
}
|
||||
|
||||
impl From<MixnetContractMixNode> for MixNode {
|
||||
fn from(value: MixnetContractMixNode) -> Self {
|
||||
let MixnetContractMixNode {
|
||||
host,
|
||||
mix_port,
|
||||
verloc_port,
|
||||
http_api_port,
|
||||
sphinx_key,
|
||||
identity_key,
|
||||
version,
|
||||
profit_margin_percent,
|
||||
} = value;
|
||||
|
||||
Self {
|
||||
host,
|
||||
mix_port,
|
||||
verloc_port,
|
||||
http_api_port,
|
||||
sphinx_key,
|
||||
identity_key,
|
||||
version,
|
||||
profit_margin_percent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/MixNodeBond.ts")
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
|
||||
pub struct MixNodeBond {
|
||||
pub pledge_amount: DecCoin,
|
||||
pub total_delegation: DecCoin,
|
||||
pub owner: String,
|
||||
pub layer: String,
|
||||
pub block_height: u64,
|
||||
pub mix_node: MixNode,
|
||||
pub proxy: Option<String>,
|
||||
pub accumulated_rewards: Option<DecCoin>,
|
||||
}
|
||||
|
||||
impl MixNodeBond {
|
||||
pub fn from_mixnet_contract_mixnode_bond(
|
||||
bond: MixnetContractMixNodeBond,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<MixNodeBond, TypesError> {
|
||||
let denom = bond.pledge_amount.denom.clone();
|
||||
Ok(MixNodeBond {
|
||||
pledge_amount: reg.attempt_convert_to_display_dec_coin(bond.pledge_amount.into())?,
|
||||
total_delegation: reg
|
||||
.attempt_convert_to_display_dec_coin(bond.total_delegation.into())?,
|
||||
owner: bond.owner.into_string(),
|
||||
layer: bond.layer.into(),
|
||||
block_height: bond.block_height,
|
||||
mix_node: bond.mix_node.into(),
|
||||
proxy: bond.proxy.map(|p| p.to_string()),
|
||||
accumulated_rewards: bond
|
||||
.accumulated_rewards
|
||||
.map(|reward| {
|
||||
// here we're making an assumption that rewards always use the same denom as the pledge
|
||||
// (which I think is a reasonable assumption)
|
||||
reg.attempt_convert_to_display_dec_coin(Coin::new(reward.u128(), denom))
|
||||
})
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
use crate::currency::DecCoin;
|
||||
use crate::error::TypesError;
|
||||
use crate::gas::{Gas, GasInfo};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator_client::nymd::cosmwasm_client::types::ExecuteResult;
|
||||
use validator_client::nymd::TxResponse;
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/SendTxResult.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct SendTxResult {
|
||||
pub block_height: u64,
|
||||
pub code: u32,
|
||||
pub details: TransactionDetails,
|
||||
pub gas_used: Gas,
|
||||
pub gas_wanted: Gas,
|
||||
pub tx_hash: String,
|
||||
pub fee: Option<DecCoin>,
|
||||
}
|
||||
|
||||
impl SendTxResult {
|
||||
pub fn new(t: TxResponse, details: TransactionDetails, fee: Option<DecCoin>) -> SendTxResult {
|
||||
SendTxResult {
|
||||
block_height: t.height.value(),
|
||||
code: t.tx_result.code.value(),
|
||||
details,
|
||||
gas_used: t.tx_result.gas_used.into(),
|
||||
gas_wanted: t.tx_result.gas_wanted.into(),
|
||||
tx_hash: t.hash.to_string(),
|
||||
fee,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/TransactionDetails.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct TransactionDetails {
|
||||
pub amount: DecCoin,
|
||||
pub from_address: String,
|
||||
pub to_address: String,
|
||||
}
|
||||
|
||||
impl TransactionDetails {
|
||||
pub fn new(amount: DecCoin, from_address: String, to_address: String) -> Self {
|
||||
TransactionDetails {
|
||||
amount,
|
||||
from_address,
|
||||
to_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/TransactionExecuteResult.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct TransactionExecuteResult {
|
||||
pub logs_json: String,
|
||||
pub data_json: String,
|
||||
pub transaction_hash: String,
|
||||
pub gas_info: GasInfo,
|
||||
pub fee: Option<DecCoin>,
|
||||
}
|
||||
|
||||
impl TransactionExecuteResult {
|
||||
pub fn from_execute_result(
|
||||
value: ExecuteResult,
|
||||
fee: Option<DecCoin>,
|
||||
) -> Result<TransactionExecuteResult, TypesError> {
|
||||
Ok(TransactionExecuteResult {
|
||||
gas_info: value.gas_info.into(),
|
||||
transaction_hash: value.transaction_hash.to_string(),
|
||||
data_json: ::serde_json::to_string_pretty(&value.data)?,
|
||||
logs_json: ::serde_json::to_string_pretty(&value.logs)?,
|
||||
fee,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/RpcTransactionResponse.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct RpcTransactionResponse {
|
||||
pub index: u32,
|
||||
pub tx_result_json: String,
|
||||
pub block_height: u64,
|
||||
pub transaction_hash: String,
|
||||
pub gas_used: Gas,
|
||||
pub gas_wanted: Gas,
|
||||
pub fee: Option<DecCoin>,
|
||||
}
|
||||
|
||||
impl RpcTransactionResponse {
|
||||
pub fn from_tx_response(
|
||||
t: &TxResponse,
|
||||
fee: Option<DecCoin>,
|
||||
) -> Result<RpcTransactionResponse, TypesError> {
|
||||
Ok(RpcTransactionResponse {
|
||||
index: t.index,
|
||||
gas_used: t.tx_result.gas_used.into(),
|
||||
gas_wanted: t.tx_result.gas_wanted.into(),
|
||||
transaction_hash: t.hash.to_string(),
|
||||
tx_result_json: ::serde_json::to_string_pretty(&t.tx_result)?,
|
||||
block_height: t.height.value(),
|
||||
fee,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
use crate::currency::{DecCoin, RegisteredCoins};
|
||||
use crate::error::TypesError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vesting_contract::vesting::Account as ContractVestingAccount;
|
||||
use vesting_contract::vesting::VestingPeriod as ContractVestingPeriod;
|
||||
use vesting_contract_common::OriginalVestingResponse as ContractOriginalVestingResponse;
|
||||
use vesting_contract_common::PledgeData as ContractPledgeData;
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/PledgeData.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct PledgeData {
|
||||
pub amount: DecCoin,
|
||||
pub block_time: u64,
|
||||
}
|
||||
|
||||
impl PledgeData {
|
||||
pub fn from_vesting_contract(
|
||||
pledge: ContractPledgeData,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(PledgeData {
|
||||
amount: reg.attempt_convert_to_display_dec_coin(pledge.amount.into())?,
|
||||
block_time: pledge.block_time.seconds(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/OriginalVestingResponse.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct OriginalVestingResponse {
|
||||
amount: DecCoin,
|
||||
number_of_periods: usize,
|
||||
period_duration: u64,
|
||||
}
|
||||
|
||||
impl OriginalVestingResponse {
|
||||
pub fn from_vesting_contract(
|
||||
res: ContractOriginalVestingResponse,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(OriginalVestingResponse {
|
||||
amount: reg.attempt_convert_to_display_dec_coin(res.amount.into())?,
|
||||
number_of_periods: res.number_of_periods,
|
||||
period_duration: res.period_duration,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/VestingAccountInfo.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct VestingAccountInfo {
|
||||
owner_address: String,
|
||||
staking_address: Option<String>,
|
||||
start_time: u64,
|
||||
periods: Vec<VestingPeriod>,
|
||||
amount: DecCoin,
|
||||
}
|
||||
|
||||
impl VestingAccountInfo {
|
||||
pub fn from_vesting_contract(
|
||||
account: ContractVestingAccount,
|
||||
reg: &RegisteredCoins,
|
||||
) -> Result<Self, TypesError> {
|
||||
Ok(VestingAccountInfo {
|
||||
owner_address: account.owner_address().to_string(),
|
||||
staking_address: account.staking_address().map(|a| a.to_string()),
|
||||
start_time: account.start_time().seconds(),
|
||||
periods: account.periods().into_iter().map(Into::into).collect(),
|
||||
amount: reg.attempt_convert_to_display_dec_coin(account.coin.into())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "ts-packages/types/src/types/rust/VestingPeriod.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct VestingPeriod {
|
||||
start_time: u64,
|
||||
period_seconds: u64,
|
||||
}
|
||||
|
||||
impl From<ContractVestingPeriod> for VestingPeriod {
|
||||
fn from(period: ContractVestingPeriod) -> Self {
|
||||
Self {
|
||||
start_time: period.start_time,
|
||||
period_seconds: period.period_seconds,
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+49
@@ -2,6 +2,12 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "Inflector"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.7.5"
|
||||
@@ -1056,6 +1062,7 @@ dependencies = [
|
||||
"serde_repr",
|
||||
"thiserror",
|
||||
"time 0.3.6",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1627,6 +1634,15 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
@@ -1699,6 +1715,29 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc59f479df54269b400dd95bc3b7e81623b3e4b9c70c8ca7125ab8341eafa64e"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ts-rs-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-macros"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f807fdb3151fee75df7485b901a89624358cd07a67a8fb1a5831bf5a07681ff"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
@@ -1809,6 +1848,7 @@ dependencies = [
|
||||
"mixnet-contract-common",
|
||||
"schemars",
|
||||
"serde",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1893,6 +1933,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
||||
@@ -62,7 +62,7 @@ pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Respon
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use bandwidth_claim_contract::payment::PagedPaymentResponse;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, from_binary};
|
||||
|
||||
@@ -91,11 +91,11 @@ pub mod tests {
|
||||
|
||||
// Contract balance should match what we initialized it as
|
||||
assert_eq!(
|
||||
coins(0, DENOM),
|
||||
coins(0, MIX_DENOM.base),
|
||||
vec![deps
|
||||
.as_ref()
|
||||
.querier
|
||||
.query_balance(env.contract.address, DENOM)
|
||||
.query_balance(env.contract.address, MIX_DENOM.base)
|
||||
.unwrap()]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,11 +63,10 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::support::tests::helpers::*;
|
||||
use coconut_bandwidth_contract_common::deposit::DepositData;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, Addr};
|
||||
use cw_multi_test::Executor;
|
||||
use serde::de::Unexpected::Str;
|
||||
|
||||
#[test]
|
||||
fn initialize_contract() {
|
||||
@@ -84,20 +83,20 @@ mod tests {
|
||||
|
||||
// Contract balance should be 0
|
||||
assert_eq!(
|
||||
coins(0, DENOM),
|
||||
coins(0, MIX_DENOM.base),
|
||||
vec![deps
|
||||
.as_ref()
|
||||
.querier
|
||||
.query_balance(env.contract.address, DENOM)
|
||||
.query_balance(env.contract.address, MIX_DENOM.base)
|
||||
.unwrap()]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deposit_and_release() {
|
||||
let init_funds = coins(10, DENOM);
|
||||
let deposit_funds = coins(1, DENOM);
|
||||
let release_funds = coins(2, DENOM);
|
||||
let init_funds = coins(10, MIX_DENOM.base);
|
||||
let deposit_funds = coins(1, MIX_DENOM.base);
|
||||
let release_funds = coins(2, MIX_DENOM.base);
|
||||
let mut app = mock_app(&init_funds);
|
||||
let multisig_addr = String::from(MULTISIG_CONTRACT);
|
||||
let pool_addr = String::from(POOL_CONTRACT);
|
||||
@@ -157,7 +156,7 @@ mod tests {
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
let pool_bal = app.wrap().query_balance(pool_addr, DENOM).unwrap();
|
||||
let pool_bal = app.wrap().query_balance(pool_addr, MIX_DENOM.base).unwrap();
|
||||
assert_eq!(pool_bal, deposit_funds[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use cosmwasm_std::StdError;
|
||||
use cw_controllers::AdminError;
|
||||
use thiserror::Error;
|
||||
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
|
||||
/// Custom errors for contract failure conditions.
|
||||
///
|
||||
@@ -22,7 +22,7 @@ pub enum ContractError {
|
||||
#[error("No coin was sent for voucher")]
|
||||
NoCoin,
|
||||
|
||||
#[error("Wrong coin denomination, you must send {}", DENOM)]
|
||||
#[error("Wrong coin denomination, you must send {}", MIX_DENOM.base)]
|
||||
WrongDenom,
|
||||
|
||||
#[error("There aren't enough funds in the contract")]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#[cfg(test)]
|
||||
pub mod helpers {
|
||||
pub const OWNER: &str = "admin0001";
|
||||
pub const SOMEBODY: &str = "somebody";
|
||||
pub const MULTISIG_CONTRACT: &str = "multisig contract address";
|
||||
pub const POOL_CONTRACT: &str = "mix pool contract address";
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use coconut_bandwidth_contract_common::events::{
|
||||
DEPOSITED_FUNDS_EVENT_TYPE, DEPOSIT_ENCRYPTION_KEY, DEPOSIT_IDENTITY_KEY, DEPOSIT_INFO,
|
||||
DEPOSIT_VALUE,
|
||||
};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
|
||||
pub(crate) fn deposit_funds(
|
||||
_deps: DepsMut<'_>,
|
||||
@@ -25,7 +25,7 @@ pub(crate) fn deposit_funds(
|
||||
if info.funds.len() > 1 {
|
||||
return Err(ContractError::MultipleDenoms);
|
||||
}
|
||||
if info.funds[0].denom != DENOM {
|
||||
if info.funds[0].denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom);
|
||||
}
|
||||
|
||||
@@ -45,10 +45,12 @@ pub(crate) fn release_funds(
|
||||
info: MessageInfo,
|
||||
funds: Coin,
|
||||
) -> Result<Response, ContractError> {
|
||||
if funds.denom != DENOM {
|
||||
if funds.denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom);
|
||||
}
|
||||
let current_balance = deps.querier.query_balance(env.contract.address, DENOM)?;
|
||||
let current_balance = deps
|
||||
.querier
|
||||
.query_balance(env.contract.address, MIX_DENOM.base)?;
|
||||
if funds.amount > current_balance.amount {
|
||||
return Err(ContractError::NotEnoughFunds);
|
||||
}
|
||||
@@ -90,7 +92,7 @@ mod tests {
|
||||
Err(ContractError::NoCoin)
|
||||
);
|
||||
|
||||
let coin = Coin::new(1000000, DENOM);
|
||||
let coin = Coin::new(1000000, MIX_DENOM.base);
|
||||
let second_coin = Coin::new(1000000, "some_denom");
|
||||
|
||||
let info = mock_info("requester", &[coin, second_coin.clone()]);
|
||||
@@ -120,7 +122,7 @@ mod tests {
|
||||
verification_key.clone(),
|
||||
encryption_key.clone(),
|
||||
);
|
||||
let coin = Coin::new(deposit_value, DENOM);
|
||||
let coin = Coin::new(deposit_value, MIX_DENOM.base);
|
||||
let info = mock_info("requester", &[coin]);
|
||||
|
||||
let tx = deposit_funds(deps.as_mut(), env.clone(), info, data).unwrap();
|
||||
@@ -169,7 +171,7 @@ mod tests {
|
||||
let mut deps = helpers::init_contract();
|
||||
let env = mock_env();
|
||||
let invalid_admin = "invalid admin";
|
||||
let funds = Coin::new(1, DENOM);
|
||||
let funds = Coin::new(1, MIX_DENOM.base);
|
||||
|
||||
let err = release_funds(
|
||||
deps.as_mut(),
|
||||
@@ -205,7 +207,7 @@ mod tests {
|
||||
fn valid_release() {
|
||||
let mut deps = helpers::init_contract();
|
||||
let env = mock_env();
|
||||
let coin = Coin::new(1, DENOM);
|
||||
let coin = Coin::new(1, MIX_DENOM.base);
|
||||
|
||||
deps.querier
|
||||
.update_balance(env.contract.address.clone(), vec![coin.clone()]);
|
||||
|
||||
@@ -475,7 +475,8 @@ pub fn migrate(deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Respons
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::support::tests;
|
||||
use config::defaults::{DEFAULT_NETWORK, DENOM};
|
||||
use config::defaults::DEFAULT_NETWORK;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, from_binary};
|
||||
use mixnet_contract_common::PagedMixnodeResponse;
|
||||
@@ -507,7 +508,7 @@ pub mod tests {
|
||||
|
||||
// Contract balance should match what we initialized it as
|
||||
assert_eq!(
|
||||
coins(0, DENOM),
|
||||
coins(0, MIX_DENOM.base),
|
||||
tests::queries::query_contract_balance(env.contract.address, deps)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ pub(crate) fn query_mixnode_delegations_paged(
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
use crate::support::tests::test_helpers;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{coin, Addr, Storage};
|
||||
use rand::Rng;
|
||||
|
||||
@@ -385,7 +385,7 @@ pub(crate) mod tests {
|
||||
let delegation = Delegation::new(
|
||||
delegation_owner.clone(),
|
||||
node_identity.clone(),
|
||||
coin(1234, DENOM),
|
||||
coin(1234, MIX_DENOM.base),
|
||||
1234,
|
||||
None,
|
||||
);
|
||||
@@ -433,7 +433,7 @@ pub(crate) mod tests {
|
||||
let delegation = Delegation::new(
|
||||
delegation_owner2,
|
||||
node_identity1.clone(),
|
||||
coin(1234, DENOM),
|
||||
coin(1234, MIX_DENOM.base),
|
||||
1234,
|
||||
None,
|
||||
);
|
||||
@@ -460,7 +460,7 @@ pub(crate) mod tests {
|
||||
let delegation = Delegation::new(
|
||||
delegation_owner1.clone(),
|
||||
node_identity2,
|
||||
coin(1234, DENOM),
|
||||
coin(1234, MIX_DENOM.base),
|
||||
1234,
|
||||
None,
|
||||
);
|
||||
|
||||
@@ -77,7 +77,7 @@ mod tests {
|
||||
mod reverse_mix_delegations {
|
||||
use super::*;
|
||||
use crate::support::tests::test_helpers;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::mock_env;
|
||||
use cosmwasm_std::{coin, Order};
|
||||
use mixnet_contract_common::Delegation;
|
||||
@@ -87,7 +87,7 @@ mod tests {
|
||||
let mut deps = test_helpers::init_contract();
|
||||
let node_identity: IdentityKey = "foo".into();
|
||||
let delegation_owner = Addr::unchecked("bar");
|
||||
let delegation = coin(12345, DENOM);
|
||||
let delegation = coin(12345, MIX_DENOM.base);
|
||||
|
||||
let dummy_data = Delegation::new(
|
||||
delegation_owner.clone(),
|
||||
@@ -125,7 +125,7 @@ mod tests {
|
||||
let node_identity2: IdentityKey = "foo2".into();
|
||||
let delegation_owner1 = Addr::unchecked("bar");
|
||||
let delegation_owner2 = Addr::unchecked("bar2");
|
||||
let delegation = coin(12345, DENOM);
|
||||
let delegation = coin(12345, MIX_DENOM.base);
|
||||
|
||||
assert!(test_helpers::read_delegation(
|
||||
deps.as_ref().storage,
|
||||
|
||||
@@ -6,7 +6,7 @@ use super::storage::{self, PENDING_DELEGATION_EVENTS};
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{
|
||||
coins, wasm_execute, Addr, Api, BankMsg, Coin, DepsMut, Env, Event, MessageInfo, Order,
|
||||
Response, Storage, Uint128, WasmMsg,
|
||||
@@ -85,7 +85,7 @@ fn validate_delegation_stake(mut delegation: Vec<Coin>) -> Result<Coin, Contract
|
||||
}
|
||||
|
||||
// check that the denomination is correct
|
||||
if delegation[0].denom != DENOM {
|
||||
if delegation[0].denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom {});
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ pub(crate) fn try_reconcile_undelegation(
|
||||
.as_ref()
|
||||
.unwrap_or(&pending_undelegate.delegate())
|
||||
.to_string(),
|
||||
amount: coins(total_funds.u128(), DENOM),
|
||||
amount: coins(total_funds.u128(), MIX_DENOM.base),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@@ -401,7 +401,7 @@ pub(crate) fn try_reconcile_undelegation(
|
||||
let msg = Some(VestingContractExecuteMsg::TrackUndelegation {
|
||||
owner: pending_undelegate.delegate().as_str().to_string(),
|
||||
mix_identity: pending_undelegate.mix_identity(),
|
||||
amount: Coin::new(total_funds.u128(), DENOM),
|
||||
amount: Coin::new(total_funds.u128(), MIX_DENOM.base),
|
||||
});
|
||||
|
||||
wasm_msg = Some(wasm_execute(proxy, &msg, vec![one_ucoin()])?);
|
||||
@@ -492,7 +492,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
Err(ContractError::MultipleDenoms),
|
||||
validate_delegation_stake(vec![
|
||||
coin(123, DENOM),
|
||||
coin(123, MIX_DENOM.base),
|
||||
coin(123, "BTC"),
|
||||
coin(123, "DOGE")
|
||||
])
|
||||
@@ -511,16 +511,16 @@ mod tests {
|
||||
fn stake_coin_must_have_value_greater_than_zero() {
|
||||
assert_eq!(
|
||||
Err(ContractError::EmptyDelegation),
|
||||
validate_delegation_stake(coins(0, DENOM))
|
||||
validate_delegation_stake(coins(0, MIX_DENOM.base))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stake_can_have_any_positive_value() {
|
||||
// this might change in the future, but right now an arbitrary (positive) value can be delegated
|
||||
assert!(validate_delegation_stake(coins(1, DENOM)).is_ok());
|
||||
assert!(validate_delegation_stake(coins(123, DENOM)).is_ok());
|
||||
assert!(validate_delegation_stake(coins(10000000000, DENOM)).is_ok());
|
||||
assert!(validate_delegation_stake(coins(1, MIX_DENOM.base)).is_ok());
|
||||
assert!(validate_delegation_stake(coins(123, MIX_DENOM.base)).is_ok());
|
||||
assert!(validate_delegation_stake(coins(10000000000, MIX_DENOM.base)).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("sender", &coins(123, DENOM)),
|
||||
mock_info("sender", &coins(123, MIX_DENOM.base)),
|
||||
"non-existent-mix-identity".into(),
|
||||
)
|
||||
);
|
||||
@@ -559,7 +559,7 @@ mod tests {
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation_owner = Addr::unchecked("sender");
|
||||
let delegation = coin(123, DENOM);
|
||||
let delegation = coin(123, MIX_DENOM.base);
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
@@ -616,7 +616,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(123, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(123, MIX_DENOM.base)),
|
||||
identity,
|
||||
)
|
||||
);
|
||||
@@ -637,7 +637,7 @@ mod tests {
|
||||
tests::fixtures::good_mixnode_pledge(),
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation = coin(123, DENOM);
|
||||
let delegation = coin(123, MIX_DENOM.base);
|
||||
let delegation_owner = Addr::unchecked("sender");
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
@@ -687,8 +687,8 @@ mod tests {
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation_owner = Addr::unchecked("sender");
|
||||
let delegation1 = coin(100, DENOM);
|
||||
let delegation2 = coin(50, DENOM);
|
||||
let delegation1 = coin(100, MIX_DENOM.base);
|
||||
let delegation2 = coin(50, MIX_DENOM.base);
|
||||
|
||||
let mut env = mock_env();
|
||||
|
||||
@@ -715,7 +715,7 @@ mod tests {
|
||||
// let expected = Delegation::new(
|
||||
// delegation_owner.clone(),
|
||||
// identity.clone(),
|
||||
// coin(delegation1.amount.u128() + delegation2.amount.u128(), DENOM),
|
||||
// coin(delegation1.amount.u128() + delegation2.amount.u128(), MIX_DENOM.base),
|
||||
// mock_env().block.height,
|
||||
// None,
|
||||
// );
|
||||
@@ -750,7 +750,7 @@ mod tests {
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation_owner = Addr::unchecked("sender");
|
||||
let delegation = coin(100, DENOM);
|
||||
let delegation = coin(100, MIX_DENOM.base);
|
||||
let env1 = mock_env();
|
||||
let mut env2 = mock_env();
|
||||
let initial_height = env1.block.height;
|
||||
@@ -815,8 +815,8 @@ mod tests {
|
||||
);
|
||||
let delegation_owner1 = Addr::unchecked("sender1");
|
||||
let delegation_owner2 = Addr::unchecked("sender2");
|
||||
let delegation1 = coin(100, DENOM);
|
||||
let delegation2 = coin(120, DENOM);
|
||||
let delegation1 = coin(100, MIX_DENOM.base);
|
||||
let delegation2 = coin(120, MIX_DENOM.base);
|
||||
let env1 = mock_env();
|
||||
let mut env2 = mock_env();
|
||||
let initial_height = env1.block.height;
|
||||
@@ -891,7 +891,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(100, MIX_DENOM.base)),
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -903,7 +903,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(50, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(50, MIX_DENOM.base)),
|
||||
identity,
|
||||
)
|
||||
);
|
||||
@@ -928,14 +928,14 @@ mod tests {
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(123, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(123, MIX_DENOM.base)),
|
||||
identity1.clone(),
|
||||
)
|
||||
.is_ok());
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(42, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(42, MIX_DENOM.base)),
|
||||
identity2.clone(),
|
||||
)
|
||||
.is_ok());
|
||||
@@ -945,7 +945,7 @@ mod tests {
|
||||
let expected1 = Delegation::new(
|
||||
delegation_owner.clone(),
|
||||
identity1.clone(),
|
||||
coin(123, DENOM),
|
||||
coin(123, MIX_DENOM.base),
|
||||
mock_env().block.height,
|
||||
None,
|
||||
);
|
||||
@@ -953,7 +953,7 @@ mod tests {
|
||||
let expected2 = Delegation::new(
|
||||
delegation_owner.clone(),
|
||||
identity2.clone(),
|
||||
coin(42, DENOM),
|
||||
coin(42, MIX_DENOM.base),
|
||||
mock_env().block.height,
|
||||
None,
|
||||
);
|
||||
@@ -989,8 +989,8 @@ mod tests {
|
||||
tests::fixtures::good_mixnode_pledge(),
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation1 = coin(123, DENOM);
|
||||
let delegation2 = coin(234, DENOM);
|
||||
let delegation1 = coin(123, MIX_DENOM.base);
|
||||
let delegation2 = coin(234, MIX_DENOM.base);
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
@@ -1026,7 +1026,7 @@ mod tests {
|
||||
deps.as_mut(),
|
||||
);
|
||||
let delegation_owner = Addr::unchecked("sender");
|
||||
let delegation_amount = coin(100, DENOM);
|
||||
let delegation_amount = coin(100, MIX_DENOM.base);
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
@@ -1118,7 +1118,7 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(100, MIX_DENOM.base)),
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1137,7 +1137,7 @@ mod tests {
|
||||
let expected_response = Response::new()
|
||||
.add_message(BankMsg::Send {
|
||||
to_address: delegation_owner.clone().into(),
|
||||
amount: coins(100, DENOM),
|
||||
amount: coins(100, MIX_DENOM.base),
|
||||
})
|
||||
.add_event(new_undelegation_event(
|
||||
&delegation_owner,
|
||||
@@ -1188,14 +1188,14 @@ mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
|
||||
mock_info(delegation_owner.as_str(), &coins(100, MIX_DENOM.base)),
|
||||
identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
_try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
|
||||
|
||||
let delegation = query_mixnode_delegation(
|
||||
let _delegation = query_mixnode_delegation(
|
||||
&deps.storage,
|
||||
&deps.api,
|
||||
identity.clone(),
|
||||
@@ -1207,7 +1207,7 @@ mod tests {
|
||||
let expected_response = Response::new()
|
||||
.add_message(BankMsg::Send {
|
||||
to_address: delegation_owner.clone().into(),
|
||||
amount: coins(100, DENOM),
|
||||
amount: coins(100, MIX_DENOM.base),
|
||||
})
|
||||
.add_event(new_undelegation_event(
|
||||
&delegation_owner,
|
||||
@@ -1251,8 +1251,8 @@ mod tests {
|
||||
);
|
||||
let delegation_owner1 = Addr::unchecked("sender1");
|
||||
let delegation_owner2 = Addr::unchecked("sender2");
|
||||
let delegation1 = coin(123, DENOM);
|
||||
let delegation2 = coin(234, DENOM);
|
||||
let delegation1 = coin(123, MIX_DENOM.base);
|
||||
let delegation2 = coin(234, MIX_DENOM.base);
|
||||
assert!(try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{Addr, StdError};
|
||||
use mixnet_contract_common::{error::MixnetContractError, IdentityKey};
|
||||
use thiserror::Error;
|
||||
@@ -33,13 +33,13 @@ pub enum ContractError {
|
||||
#[error("MIXNET ({}): Unauthorized", line!())]
|
||||
Unauthorized,
|
||||
|
||||
#[error("MIXNET ({}): Wrong coin denomination, you must send {}", line!(), DENOM)]
|
||||
#[error("MIXNET ({}): Wrong coin denomination, you must send {}", line!(), MIX_DENOM.base)]
|
||||
WrongDenom,
|
||||
|
||||
#[error("MIXNET ({}): Received multiple coin types during staking", line!())]
|
||||
MultipleDenoms,
|
||||
|
||||
#[error("MIXNET ({}): No coin was sent for the bonding, you must send {}", line!(), DENOM)]
|
||||
#[error("MIXNET ({}): No coin was sent for the bonding, you must send {}", line!(), MIX_DENOM.base)]
|
||||
NoBondFound,
|
||||
|
||||
#[error("MIXNET ({}): Provided active set size is bigger than the rewarded set", line!())]
|
||||
|
||||
@@ -36,7 +36,7 @@ pub(crate) fn gateways<'a>() -> IndexedMap<'a, IdentityKeyRef<'a>, GatewayBond,
|
||||
mod tests {
|
||||
use super::super::storage;
|
||||
use crate::support::tests;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::MockStorage;
|
||||
use cosmwasm_std::StdResult;
|
||||
use cosmwasm_std::Storage;
|
||||
@@ -84,7 +84,7 @@ mod tests {
|
||||
let pledge_amount = 1000;
|
||||
|
||||
let gateway_bond = GatewayBond {
|
||||
pledge_amount: coin(pledge_amount, DENOM),
|
||||
pledge_amount: coin(pledge_amount, MIX_DENOM.base),
|
||||
owner: node_owner,
|
||||
block_height: 12_345,
|
||||
gateway: Gateway {
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::storage;
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::support::helpers::{ensure_no_existing_bond, validate_node_identity_signature};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{
|
||||
wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Uint128,
|
||||
};
|
||||
@@ -203,7 +203,7 @@ fn validate_gateway_pledge(
|
||||
}
|
||||
|
||||
// check that the denomination is correct
|
||||
if pledge[0].denom != DENOM {
|
||||
if pledge[0].denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom {});
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ pub mod tests {
|
||||
use crate::gateways::transactions::validate_gateway_pledge;
|
||||
use crate::support::tests;
|
||||
use crate::support::tests::test_helpers;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, BankMsg, Response};
|
||||
use cosmwasm_std::{from_binary, Addr, Uint128};
|
||||
@@ -238,7 +238,7 @@ pub mod tests {
|
||||
|
||||
// if we fail validation (by say not sending enough funds
|
||||
let insufficient_bond = Into::<u128>::into(INITIAL_GATEWAY_PLEDGE) - 1;
|
||||
let info = mock_info("anyone", &coins(insufficient_bond, DENOM));
|
||||
let info = mock_info("anyone", &coins(insufficient_bond, MIX_DENOM.base));
|
||||
let (msg, _) = tests::messages::valid_bond_gateway_msg("anyone");
|
||||
|
||||
// we are informed that we didn't send enough funds
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{StdResult, Storage, Uint128};
|
||||
use cw_storage_plus::{Index, IndexList, IndexedSnapshotMap, Map, Strategy, UniqueIndex};
|
||||
use mixnet_contract_common::{
|
||||
@@ -171,7 +171,7 @@ pub(crate) fn read_full_mixnode_bond(
|
||||
Ok(Some(MixNodeBond {
|
||||
pledge_amount: stored_bond.pledge_amount,
|
||||
total_delegation: Coin {
|
||||
denom: DENOM.to_owned(),
|
||||
denom: MIX_DENOM.base.to_owned(),
|
||||
amount: total_delegation.unwrap_or_default(),
|
||||
},
|
||||
owner: stored_bond.owner,
|
||||
@@ -190,7 +190,7 @@ mod tests {
|
||||
use super::super::storage;
|
||||
use super::*;
|
||||
use crate::support::tests;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::MockStorage;
|
||||
use cosmwasm_std::{coin, Addr, Uint128};
|
||||
use mixnet_contract_common::{IdentityKey, MixNode};
|
||||
@@ -223,7 +223,7 @@ mod tests {
|
||||
let pledge_value = 1000000000;
|
||||
|
||||
let mixnode_bond = StoredMixnodeBond {
|
||||
pledge_amount: coin(pledge_value, DENOM),
|
||||
pledge_amount: coin(pledge_value, MIX_DENOM.base),
|
||||
owner: node_owner,
|
||||
layer: Layer::One,
|
||||
block_height: 12_345,
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::mixnodes::layer_queries::query_layer_distribution;
|
||||
use crate::mixnodes::storage::StoredMixnodeBond;
|
||||
use crate::support::helpers::{ensure_no_existing_bond, validate_node_identity_signature};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{
|
||||
wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Storage, Uint128,
|
||||
};
|
||||
@@ -364,7 +364,7 @@ fn validate_mixnode_pledge(
|
||||
}
|
||||
|
||||
// check that the denomination is correct
|
||||
if pledge[0].denom != DENOM {
|
||||
if pledge[0].denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom {});
|
||||
}
|
||||
|
||||
@@ -381,15 +381,13 @@ fn validate_mixnode_pledge(
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use std::f64::MIN;
|
||||
|
||||
use super::*;
|
||||
use crate::contract::{execute, query, INITIAL_MIXNODE_PLEDGE};
|
||||
use crate::error::ContractError;
|
||||
use crate::mixnodes::transactions::validate_mixnode_pledge;
|
||||
use crate::support::tests;
|
||||
use crate::support::tests::test_helpers;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, BankMsg, Response};
|
||||
use cosmwasm_std::{from_binary, Addr, Uint128};
|
||||
@@ -404,7 +402,7 @@ pub mod tests {
|
||||
|
||||
// if we don't send enough funds
|
||||
let insufficient_bond = Into::<u128>::into(INITIAL_MIXNODE_PLEDGE) - 1;
|
||||
let info = mock_info("anyone", &coins(insufficient_bond, DENOM));
|
||||
let info = mock_info("anyone", &coins(insufficient_bond, MIX_DENOM.base));
|
||||
let (msg, _) = tests::messages::valid_bond_mixnode_msg("anyone");
|
||||
|
||||
// we are informed that we didn't send enough funds
|
||||
|
||||
@@ -79,7 +79,7 @@ pub(crate) mod tests {
|
||||
use crate::delegations::transactions::try_delegate_to_mixnode;
|
||||
use crate::interval::storage::{save_epoch, save_epoch_reward_params};
|
||||
use crate::rewards::transactions::try_reward_mixnode;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{coin, Addr};
|
||||
use mixnet_contract_common::{
|
||||
Interval, RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT,
|
||||
@@ -181,7 +181,10 @@ pub(crate) mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info(&*format!("delegator{:04}", i), &[coin(200_000000, DENOM)]),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&[coin(200_000000, MIX_DENOM.base)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::mixnodes::storage::mixnodes;
|
||||
use crate::mixnodes::storage::{self as mixnodes_storage, StoredMixnodeBond};
|
||||
use crate::rewards::helpers;
|
||||
use crate::support::helpers::is_authorized;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{
|
||||
coins, wasm_execute, Addr, Api, BankMsg, Coin, DepsMut, Env, MessageInfo, Order, Response,
|
||||
Storage, Uint128,
|
||||
@@ -105,7 +105,7 @@ fn _try_claim_operator_reward(
|
||||
|
||||
let return_tokens = BankMsg::Send {
|
||||
to_address: proxy.as_ref().unwrap_or(&owner).to_string(),
|
||||
amount: coins(reward.u128(), DENOM),
|
||||
amount: coins(reward.u128(), MIX_DENOM.base),
|
||||
};
|
||||
|
||||
let mut response = Response::default()
|
||||
@@ -115,7 +115,7 @@ fn _try_claim_operator_reward(
|
||||
if let Some(proxy) = proxy {
|
||||
let msg = Some(VestingContractExecuteMsg::TrackReward {
|
||||
address: owner.to_string(),
|
||||
amount: Coin::new(reward.u128(), DENOM),
|
||||
amount: Coin::new(reward.u128(), MIX_DENOM.base),
|
||||
});
|
||||
|
||||
let wasm_msg = wasm_execute(proxy, &msg, vec![one_ucoin()])?;
|
||||
@@ -153,7 +153,7 @@ pub fn _try_claim_delegator_reward(
|
||||
|
||||
let return_tokens = BankMsg::Send {
|
||||
to_address: proxy.as_ref().unwrap_or(&owner).to_string(),
|
||||
amount: coins(reward.u128(), DENOM),
|
||||
amount: coins(reward.u128(), MIX_DENOM.base),
|
||||
};
|
||||
|
||||
let mut response =
|
||||
@@ -169,7 +169,7 @@ pub fn _try_claim_delegator_reward(
|
||||
if let Some(proxy) = proxy {
|
||||
let msg = Some(VestingContractExecuteMsg::TrackReward {
|
||||
address: owner.to_string(),
|
||||
amount: Coin::new(reward.u128(), DENOM),
|
||||
amount: Coin::new(reward.u128(), MIX_DENOM.base),
|
||||
});
|
||||
|
||||
let wasm_msg = wasm_execute(proxy, &msg, vec![one_ucoin()])?;
|
||||
@@ -436,7 +436,7 @@ pub fn _try_compound_delegator_reward(
|
||||
owner_address,
|
||||
Coin {
|
||||
amount: compounded_delegation,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
proxy,
|
||||
)?;
|
||||
@@ -721,7 +721,7 @@ pub mod tests {
|
||||
use crate::support::tests;
|
||||
use crate::support::tests::test_helpers;
|
||||
use az::CheckedCast;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::{coin, coins, Addr, StdError, Timestamp, Uint128};
|
||||
use mixnet_contract_common::events::{
|
||||
@@ -737,7 +737,7 @@ pub mod tests {
|
||||
let mut deps = test_helpers::init_contract();
|
||||
let mut env = mock_env();
|
||||
let sender = rewarding_validator_address(&deps.storage).unwrap();
|
||||
let info = mock_info(&sender, &coins(1000, DENOM));
|
||||
let info = mock_info(&sender, &coins(1000, MIX_DENOM.base));
|
||||
crate::interval::transactions::init_epoch(&mut deps.storage, env.clone()).unwrap();
|
||||
|
||||
// bond the node
|
||||
@@ -878,7 +878,7 @@ pub mod tests {
|
||||
let initial_bond = 10000_000000;
|
||||
let initial_delegation = 20000_000000;
|
||||
let mixnode_bond = StoredMixnodeBond {
|
||||
pledge_amount: coin(initial_bond, DENOM),
|
||||
pledge_amount: coin(initial_bond, MIX_DENOM.base),
|
||||
owner: node_owner,
|
||||
layer: Layer::One,
|
||||
block_height: env.block.height,
|
||||
@@ -918,7 +918,7 @@ pub mod tests {
|
||||
&Delegation::new(
|
||||
Addr::unchecked("delegator"),
|
||||
node_identity.clone(),
|
||||
coin(initial_delegation, DENOM),
|
||||
coin(initial_delegation, MIX_DENOM.base),
|
||||
env.block.height,
|
||||
None,
|
||||
),
|
||||
@@ -1098,7 +1098,7 @@ pub mod tests {
|
||||
assert_eq!(circulating_supply, 750_000_000_000_000u128);
|
||||
|
||||
let sender = Addr::unchecked("alice");
|
||||
let stake = coins(10_000_000_000, DENOM);
|
||||
let stake = coins(10_000_000_000, MIX_DENOM.base);
|
||||
|
||||
let keypair = crypto::asymmetric::identity::KeyPair::new(&mut thread_rng());
|
||||
let owner_signature = keypair
|
||||
@@ -1151,14 +1151,14 @@ pub mod tests {
|
||||
let node_owner: Addr = Addr::unchecked("johnny");
|
||||
let node_identity_2 = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10_000_000_000, DENOM),
|
||||
coins(10_000_000_000, MIX_DENOM.base),
|
||||
deps.as_mut(),
|
||||
);
|
||||
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("alice_d1", &[coin(8000_000000, DENOM)]),
|
||||
mock_info("alice_d1", &[coin(8000_000000, MIX_DENOM.base)]),
|
||||
node_identity_1.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1166,7 +1166,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("alice_d2", &[coin(2000_000000, DENOM)]),
|
||||
mock_info("alice_d2", &[coin(2000_000000, MIX_DENOM.base)]),
|
||||
node_identity_1.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1174,7 +1174,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("bob_d1", &[coin(8000_000000, DENOM)]),
|
||||
mock_info("bob_d1", &[coin(8000_000000, MIX_DENOM.base)]),
|
||||
node_identity_2.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1182,7 +1182,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("bob_d2", &[coin(2000_000000, DENOM)]),
|
||||
mock_info("bob_d2", &[coin(2000_000000, MIX_DENOM.base)]),
|
||||
node_identity_2.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1190,14 +1190,14 @@ pub mod tests {
|
||||
let node_owner: Addr = Addr::unchecked("alicebob");
|
||||
let node_identity_3 = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10_000_000_000 * 2, DENOM),
|
||||
coins(10_000_000_000 * 2, MIX_DENOM.base),
|
||||
deps.as_mut(),
|
||||
);
|
||||
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("alicebob_d1", &[coin(8000_000000 * 2, DENOM)]),
|
||||
mock_info("alicebob_d1", &[coin(8000_000000 * 2, MIX_DENOM.base)]),
|
||||
node_identity_3.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1205,7 +1205,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("alicebob_d2", &[coin(2000_000000 * 2, DENOM)]),
|
||||
mock_info("alicebob_d2", &[coin(2000_000000 * 2, MIX_DENOM.base)]),
|
||||
node_identity_3.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1216,7 +1216,6 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let info = mock_info(rewarding_validator_address.as_ref(), &[]);
|
||||
env.block.height += 2 * constants::MINIMUM_BLOCK_AGE_FOR_REWARDING;
|
||||
|
||||
let mix_1 = mixnodes_storage::read_full_mixnode_bond(&deps.storage, &node_identity_1)
|
||||
@@ -1305,7 +1304,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info("alice_d1", &[coin(8000_000000, DENOM)]),
|
||||
mock_info("alice_d1", &[coin(8000_000000, MIX_DENOM.base)]),
|
||||
node_identity_1.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1506,7 +1505,7 @@ pub mod tests {
|
||||
);
|
||||
assert_eq!(mix_2_reward_result.reward().int(), 129557u128);
|
||||
|
||||
let mix_3_reward_result = mix_3.reward(¶ms3);
|
||||
let _mix_3_reward_result = mix_3.reward(¶ms3);
|
||||
|
||||
// assert_eq!(mix_3_reward_result.reward().int(), mix_1_reward_result.reward().int() + mix_2_reward_result.reward().int());
|
||||
}
|
||||
@@ -1533,14 +1532,14 @@ pub mod tests {
|
||||
let node_owner: Addr = Addr::unchecked("alice");
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10_000_000_000, DENOM),
|
||||
coins(10_000_000_000, MIX_DENOM.base),
|
||||
deps.as_mut(),
|
||||
);
|
||||
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("alice_d1", &[coin(8000_000000, DENOM)]),
|
||||
mock_info("alice_d1", &[coin(8000_000000, MIX_DENOM.base)]),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1548,7 +1547,7 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
mock_env(),
|
||||
mock_info("alice_d2", &[coin(2000_000000, DENOM)]),
|
||||
mock_info("alice_d2", &[coin(2000_000000, MIX_DENOM.base)]),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1698,7 +1697,7 @@ pub mod tests {
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10000_000_000, DENOM),
|
||||
coins(10000_000_000, MIX_DENOM.base),
|
||||
deps.as_mut(),
|
||||
);
|
||||
|
||||
@@ -1725,7 +1724,7 @@ pub mod tests {
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
node_owner.as_str(),
|
||||
coins(10000_000_000, DENOM),
|
||||
coins(10000_000_000, MIX_DENOM.base),
|
||||
deps.as_mut(),
|
||||
);
|
||||
|
||||
@@ -1733,7 +1732,10 @@ pub mod tests {
|
||||
try_delegate_to_mixnode(
|
||||
deps.as_mut(),
|
||||
env.clone(),
|
||||
mock_info(&*format!("delegator{:04}", i), &[coin(2000_000000, DENOM)]),
|
||||
mock_info(
|
||||
&*format!("delegator{:04}", i),
|
||||
&[coin(2000_000000, MIX_DENOM.base)],
|
||||
),
|
||||
node_identity.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::contract::INITIAL_MIXNODE_PLEDGE;
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use crate::{mixnodes::storage::StoredMixnodeBond, support::tests};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{coin, Addr, Coin};
|
||||
use mixnet_contract_common::reward_params::NodeRewardParams;
|
||||
use mixnet_contract_common::{Gateway, GatewayBond, Layer, MixNode};
|
||||
@@ -37,7 +37,7 @@ pub fn gateway_bond_fixture(owner: &str) -> GatewayBond {
|
||||
..tests::fixtures::gateway_fixture()
|
||||
};
|
||||
GatewayBond::new(
|
||||
coin(50, DENOM),
|
||||
coin(50, MIX_DENOM.base),
|
||||
Addr::unchecked(owner),
|
||||
12_345,
|
||||
gateway,
|
||||
@@ -47,7 +47,7 @@ pub fn gateway_bond_fixture(owner: &str) -> GatewayBond {
|
||||
|
||||
pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::StoredMixnodeBond {
|
||||
StoredMixnodeBond::new(
|
||||
coin(50, DENOM),
|
||||
coin(50, MIX_DENOM.base),
|
||||
Addr::unchecked(owner),
|
||||
Layer::One,
|
||||
12_345,
|
||||
@@ -64,14 +64,14 @@ pub(crate) fn stored_mixnode_bond_fixture(owner: &str) -> mixnodes_storage::Stor
|
||||
|
||||
pub fn good_mixnode_pledge() -> Vec<Coin> {
|
||||
vec![Coin {
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
amount: INITIAL_MIXNODE_PLEDGE,
|
||||
}]
|
||||
}
|
||||
|
||||
pub fn good_gateway_pledge() -> Vec<Coin> {
|
||||
vec![Coin {
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
amount: INITIAL_MIXNODE_PLEDGE,
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub mod test_helpers {
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use crate::mixnodes::transactions::try_add_mixnode;
|
||||
use crate::support::tests;
|
||||
use config::defaults::{DEFAULT_NETWORK, DENOM};
|
||||
use config::defaults::{DEFAULT_NETWORK, MIX_DENOM};
|
||||
use cosmwasm_std::testing::mock_dependencies;
|
||||
use cosmwasm_std::testing::mock_env;
|
||||
use cosmwasm_std::testing::mock_info;
|
||||
@@ -111,7 +111,7 @@ pub mod test_helpers {
|
||||
let delegation = Delegation {
|
||||
owner: Addr::unchecked(owner.into()),
|
||||
node_identity: mix.into(),
|
||||
amount: coin(12345, DENOM),
|
||||
amount: coin(12345, MIX_DENOM.base),
|
||||
block_height: block_height,
|
||||
proxy: None,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{
|
||||
from_binary,
|
||||
testing::{mock_env, MockApi, MockQuerier, MockStorage},
|
||||
@@ -45,5 +45,5 @@ pub fn query_contract_balance(
|
||||
deps: OwnedDeps<MockStorage, MockApi, MockQuerier>,
|
||||
) -> Vec<Coin> {
|
||||
let querier = deps.as_ref().querier;
|
||||
vec![querier.query_balance(address, DENOM).unwrap()]
|
||||
vec![querier.query_balance(address, MIX_DENOM.base).unwrap()]
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::traits::{
|
||||
DelegatingAccount, GatewayBondingAccount, MixnodeBondingAccount, VestingAccount,
|
||||
};
|
||||
use crate::vesting::{populate_vesting_periods, Account};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{
|
||||
coin, entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, MessageInfo, QueryResponse,
|
||||
Response, Timestamp,
|
||||
@@ -147,8 +147,11 @@ pub fn try_withdraw_vested_coins(
|
||||
info: MessageInfo,
|
||||
deps: DepsMut<'_>,
|
||||
) -> Result<Response, ContractError> {
|
||||
if amount.denom != DENOM {
|
||||
return Err(ContractError::WrongDenom(amount.denom, DENOM.to_string()));
|
||||
if amount.denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom(
|
||||
amount.denom,
|
||||
MIX_DENOM.base.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let address = info.sender.clone();
|
||||
@@ -611,10 +614,10 @@ fn validate_funds(funds: &[Coin]) -> Result<Coin, ContractError> {
|
||||
return Err(ContractError::MultipleDenoms);
|
||||
}
|
||||
|
||||
if funds[0].denom != DENOM {
|
||||
if funds[0].denom != MIX_DENOM.base {
|
||||
return Err(ContractError::WrongDenom(
|
||||
funds[0].denom.clone(),
|
||||
DENOM.to_string(),
|
||||
MIX_DENOM.base.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
pub mod helpers {
|
||||
use crate::contract::instantiate;
|
||||
use crate::vesting::{populate_vesting_periods, Account};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier};
|
||||
use cosmwasm_std::{Addr, Coin, Empty, Env, MemoryStorage, OwnedDeps, Storage, Uint128};
|
||||
use vesting_contract_common::messages::{InitMsg, VestingSpecification};
|
||||
@@ -31,7 +31,7 @@ pub mod helpers {
|
||||
Some(Addr::unchecked("staking")),
|
||||
Coin {
|
||||
amount: Uint128::new(1_000_000_000_000),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
start_time_ts,
|
||||
periods,
|
||||
@@ -50,7 +50,7 @@ pub mod helpers {
|
||||
Some(Addr::unchecked("staking")),
|
||||
Coin {
|
||||
amount: Uint128::new(1_000_000_000_000),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
start_time,
|
||||
periods,
|
||||
|
||||
@@ -25,11 +25,11 @@ fn generate_storage_key(storage: &mut dyn Storage) -> Result<u32, ContractError>
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||
pub struct Account {
|
||||
owner_address: Addr,
|
||||
staking_address: Option<Addr>,
|
||||
start_time: Timestamp,
|
||||
periods: Vec<VestingPeriod>,
|
||||
coin: Coin,
|
||||
pub owner_address: Addr,
|
||||
pub staking_address: Option<Addr>,
|
||||
pub start_time: Timestamp,
|
||||
pub periods: Vec<VestingPeriod>,
|
||||
pub coin: Coin,
|
||||
storage_key: u32,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::errors::ContractError;
|
||||
use crate::storage::{delete_account, save_account, DELEGATIONS};
|
||||
use crate::traits::VestingAccount;
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::{Addr, Coin, Env, Order, Storage, Timestamp, Uint128};
|
||||
use vesting_contract_common::{OriginalVestingResponse, Period};
|
||||
|
||||
@@ -38,7 +38,7 @@ impl VestingAccount for Account {
|
||||
.u128(),
|
||||
),
|
||||
),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ impl VestingAccount for Account {
|
||||
.u128()
|
||||
.saturating_sub(self.locked_coins(block_time, env, storage)?.amount.u128()),
|
||||
),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -69,15 +69,15 @@ impl VestingAccount for Account {
|
||||
let amount = match period {
|
||||
Period::Before => Coin {
|
||||
amount: Uint128::new(0),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
Period::In(idx) => Coin {
|
||||
amount: Uint128::new(self.tokens_per_period()? * idx as u128),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
Period::After => Coin {
|
||||
amount: self.coin.amount,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
};
|
||||
Ok(amount)
|
||||
@@ -91,7 +91,7 @@ impl VestingAccount for Account {
|
||||
Ok(Coin {
|
||||
amount: self.get_original_vesting().amount().amount
|
||||
- self.get_vested_coins(block_time, env)?.amount,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ impl VestingAccount for Account {
|
||||
|
||||
Ok(Coin {
|
||||
amount,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ impl VestingAccount for Account {
|
||||
|
||||
Ok(Coin {
|
||||
amount,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ impl VestingAccount for Account {
|
||||
|
||||
Ok(Coin {
|
||||
amount,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -217,12 +217,12 @@ impl VestingAccount for Account {
|
||||
let amount = bond.amount().amount - bonded_free.amount;
|
||||
Ok(Coin {
|
||||
amount,
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
} else {
|
||||
Ok(Coin {
|
||||
amount: Uint128::zero(),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ mod tests {
|
||||
use crate::traits::DelegatingAccount;
|
||||
use crate::traits::VestingAccount;
|
||||
use crate::traits::{GatewayBondingAccount, MixnodeBondingAccount};
|
||||
use config::defaults::DENOM;
|
||||
use config::defaults::MIX_DENOM;
|
||||
use cosmwasm_std::testing::{mock_env, mock_info};
|
||||
use cosmwasm_std::{coins, Addr, Coin, Timestamp, Uint128};
|
||||
use mixnet_contract_common::{Gateway, MixNode};
|
||||
@@ -55,7 +55,7 @@ mod tests {
|
||||
fn test_account_creation() {
|
||||
let mut deps = init_contract();
|
||||
let env = mock_env();
|
||||
let info = mock_info("not_admin", &coins(1_000_000_000_000, DENOM));
|
||||
let info = mock_info("not_admin", &coins(1_000_000_000_000, MIX_DENOM.base));
|
||||
let msg = ExecuteMsg::CreateAccount {
|
||||
owner_address: "owner".to_string(),
|
||||
staking_address: Some("staking".to_string()),
|
||||
@@ -65,7 +65,7 @@ mod tests {
|
||||
let response = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone());
|
||||
assert!(response.is_err());
|
||||
|
||||
let info = mock_info("admin", &coins(1_000_000_000_000, DENOM));
|
||||
let info = mock_info("admin", &coins(1_000_000_000_000, MIX_DENOM.base));
|
||||
let _response = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone());
|
||||
let created_account = load_account(&Addr::unchecked("owner"), &deps.storage)
|
||||
.unwrap()
|
||||
@@ -131,7 +131,7 @@ mod tests {
|
||||
let msg = ExecuteMsg::WithdrawVestedCoins {
|
||||
amount: Coin {
|
||||
amount: Uint128::new(1),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
};
|
||||
let info = mock_info("new_owner", &[]);
|
||||
@@ -262,7 +262,7 @@ mod tests {
|
||||
|
||||
let delegation = Coin {
|
||||
amount: Uint128::new(500_000_000_000),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
};
|
||||
|
||||
let ok = account.try_delegate_to_mixnode(
|
||||
@@ -388,7 +388,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(1_000_000_000_001),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -399,7 +399,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(500_000_000_000),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -414,7 +414,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(500_000_000_001),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -510,7 +510,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(1_000_000_000_001),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -522,7 +522,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(500_000_000_000),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -538,7 +538,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(500_000_000_001),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -630,7 +630,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(1_000_000_000_001),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -642,7 +642,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(500_000_000_000),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
@@ -658,7 +658,7 @@ mod tests {
|
||||
"alice".to_string(),
|
||||
Coin {
|
||||
amount: Uint128::new(500_000_000_001),
|
||||
denom: DENOM.to_string(),
|
||||
denom: MIX_DENOM.base.to_string(),
|
||||
},
|
||||
&env,
|
||||
&mut deps.storage,
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"packages": [
|
||||
"ts-packages/*"
|
||||
"ts-packages/*",
|
||||
"nym-wallet"
|
||||
],
|
||||
"version": "0.0.0"
|
||||
}
|
||||
|
||||
Generated
+50
@@ -2785,6 +2785,7 @@ dependencies = [
|
||||
"serde_repr",
|
||||
"thiserror",
|
||||
"time 0.3.7",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2997,6 +2998,49 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"coconut-interface",
|
||||
"config",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"eyre",
|
||||
"itertools",
|
||||
"log",
|
||||
"mixnet-contract-common",
|
||||
"reqwest",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum 0.23.0",
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-client",
|
||||
"vesting-contract",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"config",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"mixnet-contract-common",
|
||||
"nym-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strum 0.23.0",
|
||||
"ts-rs",
|
||||
"validator-client",
|
||||
"vesting-contract",
|
||||
"vesting-contract-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym_wallet"
|
||||
version = "1.0.4"
|
||||
@@ -3009,6 +3053,7 @@ dependencies = [
|
||||
"coconut-interface",
|
||||
"colored",
|
||||
"config",
|
||||
"cosmrs",
|
||||
"cosmwasm-std",
|
||||
"dirs",
|
||||
"dotenv",
|
||||
@@ -3017,6 +3062,8 @@ dependencies = [
|
||||
"itertools",
|
||||
"log",
|
||||
"mixnet-contract-common",
|
||||
"nym-types",
|
||||
"nym-wallet-types",
|
||||
"once_cell",
|
||||
"pretty_env_logger",
|
||||
"rand 0.6.5",
|
||||
@@ -5450,6 +5497,7 @@ dependencies = [
|
||||
"mixnet-contract-common",
|
||||
"schemars",
|
||||
"serde",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5481,6 +5529,7 @@ dependencies = [
|
||||
"sha2 0.9.9",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"ts-rs",
|
||||
"url",
|
||||
"validator-api-requests",
|
||||
"vesting-contract",
|
||||
@@ -5541,6 +5590,7 @@ dependencies = [
|
||||
"mixnet-contract-common",
|
||||
"schemars",
|
||||
"serde",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -4,4 +4,5 @@ resolver = "2"
|
||||
members = [
|
||||
"src-tauri",
|
||||
"wallet-recovery-cli",
|
||||
"nym-wallet-types"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
[package]
|
||||
name = "nym-wallet-types"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.58"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
cosmwasm-std = "1.0.0-beta8"
|
||||
cosmrs = "0.7.0"
|
||||
|
||||
config = { path = "../../common/config" }
|
||||
mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
validator-client = { path = "../../common/client-libs/validator-client", features = [
|
||||
"nymd-client",
|
||||
] }
|
||||
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
# Used for Type conversion, can be extracted but its a lot of work
|
||||
vesting-contract = { path = "../../contracts/vesting" }
|
||||
|
||||
nym-types = { path = "../../common/types" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
generate-ts = []
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export interface AppEnv { ADMIN_ADDRESS: string | null, SHOW_TERMINAL: string | null, }
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export interface ValidatorUrl { url: string, name: string | null, }
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export interface Validator { nymd_url: string, nymd_name: string | null, api_url: string | null, }
|
||||
@@ -0,0 +1,44 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use cosmwasm_std::Uint128;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
use nym_types::error::TypesError;
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "nym-wallet/src/types/rust/StateParams.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct TauriContractStateParams {
|
||||
minimum_mixnode_pledge: String,
|
||||
minimum_gateway_pledge: String,
|
||||
mixnode_rewarded_set_size: u32,
|
||||
mixnode_active_set_size: u32,
|
||||
}
|
||||
|
||||
impl From<ContractStateParams> for TauriContractStateParams {
|
||||
fn from(p: ContractStateParams) -> TauriContractStateParams {
|
||||
TauriContractStateParams {
|
||||
minimum_mixnode_pledge: p.minimum_mixnode_pledge.to_string(),
|
||||
minimum_gateway_pledge: p.minimum_gateway_pledge.to_string(),
|
||||
mixnode_rewarded_set_size: p.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
type Error = TypesError;
|
||||
|
||||
fn try_from(p: TauriContractStateParams) -> Result<ContractStateParams, Self::Error> {
|
||||
Ok(ContractStateParams {
|
||||
minimum_mixnode_pledge: Uint128::try_from(p.minimum_mixnode_pledge.as_str())?,
|
||||
minimum_gateway_pledge: Uint128::try_from(p.minimum_gateway_pledge.as_str())?,
|
||||
mixnode_rewarded_set_size: p.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export, export_to = "nym-wallet/src/types/rust/AppEnv.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct AppEnv {
|
||||
pub ADMIN_ADDRESS: Option<String>,
|
||||
pub SHOW_TERMINAL: Option<String>,
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
use mixnet_contract_common::Interval;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "nym-wallet/src/types/rust/Epoch.ts")
|
||||
)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct Epoch {
|
||||
id: u32,
|
||||
start: i64,
|
||||
end: i64,
|
||||
duration_seconds: u64,
|
||||
}
|
||||
|
||||
impl From<Interval> for Epoch {
|
||||
fn from(interval: Interval) -> Self {
|
||||
Self {
|
||||
id: interval.id(),
|
||||
start: interval.start_unix_timestamp(),
|
||||
end: interval.end_unix_timestamp(),
|
||||
duration_seconds: interval.length().as_secs(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
pub mod admin;
|
||||
pub mod app;
|
||||
pub mod epoch;
|
||||
pub mod network;
|
||||
pub mod network_config;
|
||||
@@ -1,15 +1,21 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use config::defaults::all::Network as ConfigNetwork;
|
||||
use config::defaults::{mainnet, qa, sandbox};
|
||||
use cosmrs::Denom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use strum::EnumIter;
|
||||
|
||||
use config::defaults::all::Network as ConfigNetwork;
|
||||
use config::defaults::{mainnet, qa, sandbox};
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/network.ts"))]
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "nym-wallet/src/types/rust/Network.ts")
|
||||
)]
|
||||
#[derive(Copy, Clone, Debug, Deserialize, EnumIter, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum Network {
|
||||
QA,
|
||||
@@ -22,12 +28,29 @@ impl Network {
|
||||
self.to_string().to_lowercase()
|
||||
}
|
||||
|
||||
pub fn denom(&self) -> &str {
|
||||
#[deprecated]
|
||||
pub fn denom(&self) -> Denom {
|
||||
match self {
|
||||
// network defaults should be correctly formatted
|
||||
Network::QA => qa::DENOM,
|
||||
Network::SANDBOX => sandbox::DENOM,
|
||||
Network::MAINNET => mainnet::DENOM,
|
||||
Network::QA => Denom::from_str(qa::DENOM).unwrap(),
|
||||
Network::SANDBOX => Denom::from_str(sandbox::DENOM).unwrap(),
|
||||
Network::MAINNET => Denom::from_str(mainnet::DENOM).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_mix_denom(&self) -> &str {
|
||||
match self {
|
||||
Network::QA => qa::MIX_DENOM.base,
|
||||
Network::SANDBOX => sandbox::MIX_DENOM.base,
|
||||
Network::MAINNET => mainnet::MIX_DENOM.base,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_mix_denom(&self) -> &str {
|
||||
match self {
|
||||
Network::QA => qa::MIX_DENOM.display,
|
||||
Network::SANDBOX => sandbox::MIX_DENOM.display,
|
||||
Network::MAINNET => mainnet::MIX_DENOM.display,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
// When the UI queries validator urls we use this type
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export_to = "nym-wallet/src/types/rust/ValidatorUrls.ts")
|
||||
)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ValidatorUrls {
|
||||
pub urls: Vec<ValidatorUrl>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export, export_to = "nym-wallet/src/types/rust/ValidatorUrl.ts")
|
||||
)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ValidatorUrl {
|
||||
pub url: String,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
// The type used when adding or removing validators, effectively the input.
|
||||
// NOTE: we should consider if we want to split this up
|
||||
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "generate-ts",
|
||||
ts(export, export_to = "nym-wallet/src/types/rust/ValidatorUrls.ts")
|
||||
)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Validator {
|
||||
pub nymd_url: String,
|
||||
pub nymd_name: Option<String>,
|
||||
pub api_url: Option<String>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Validator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let nymd_url = format!("nymd_url: {}", self.nymd_url);
|
||||
let api_url = self
|
||||
.api_url
|
||||
.as_ref()
|
||||
.map(|api_url| format!(", api_url: {}", api_url))
|
||||
.unwrap_or_default();
|
||||
write!(f, "{nymd_url}{api_url}")
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,11 @@
|
||||
"@mui/icons-material": "^5.2.0",
|
||||
"@mui/material": "^5.2.2",
|
||||
"@mui/styles": "^5.2.2",
|
||||
"@mui/utils": "^5.7.0",
|
||||
"@nymproject/mui-theme": "^1.0.0",
|
||||
"@nymproject/react": "^1.0.0",
|
||||
"@nymproject/types": "^1.0.0",
|
||||
"@storybook/react": "^6.4.22",
|
||||
"@tauri-apps/api": "^1.0.0-rc.1",
|
||||
"bs58": "^4.0.1",
|
||||
"clsx": "^1.1.1",
|
||||
@@ -41,7 +44,7 @@
|
||||
"react-dom": "^17.0.2",
|
||||
"react-error-boundary": "^3.1.3",
|
||||
"react-hook-form": "^7.14.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-router-dom": "6",
|
||||
"semver": "^6.3.0",
|
||||
"string-to-color": "^2.2.2",
|
||||
"use-clipboard-copy": "^0.2.0",
|
||||
@@ -55,12 +58,6 @@
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@nymproject/eslint-config-react-typescript": "^1.0.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
|
||||
"@storybook/addon-actions": "^6.4.19",
|
||||
"@storybook/addon-essentials": "^6.4.19",
|
||||
"@storybook/addon-interactions": "^6.4.19",
|
||||
"@storybook/addon-links": "^6.4.19",
|
||||
"@storybook/react": "^6.4.19",
|
||||
"@storybook/testing-library": "^0.0.9",
|
||||
"@svgr/webpack": "^6.1.1",
|
||||
"@tauri-apps/cli": "^1.0.0-rc.5",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||
<title>Nym Wallet</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id='root'></div>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Nym Wallet</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -48,6 +48,7 @@ base64 = "0.13"
|
||||
zeroize = "1.4.3"
|
||||
|
||||
cosmwasm-std = "1.0.0"
|
||||
cosmrs = "0.7.0"
|
||||
|
||||
validator-client = { path = "../../common/client-libs/validator-client", features = [
|
||||
"nymd-client",
|
||||
@@ -58,11 +59,14 @@ config = { path = "../../common/config" }
|
||||
coconut-interface = { path = "../../common/coconut-interface" }
|
||||
# Used for Type conversion, can be extracted but its a lot of work
|
||||
vesting-contract = { path = "../../contracts/vesting" }
|
||||
nym-types = { path = "../../common/types" }
|
||||
nym-wallet-types = { path = "../nym-wallet-types" }
|
||||
|
||||
[dev-dependencies]
|
||||
ts-rs = "6.1.2"
|
||||
tempfile = "3.3.0"
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
generate-ts = []
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
// This should be moved out of the wallet, and used as a primary coin type throughout the codebase
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::network::Network;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
use strum::IntoEnumIterator;
|
||||
use validator_client::nymd::CosmosCoin;
|
||||
use validator_client::nymd::Denom as CosmosDenom;
|
||||
use validator_client::nymd::{Coin as BackendCoin, CosmWasmCoin};
|
||||
|
||||
const MINOR_IN_MAJOR: f64 = 1_000_000.;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export, export_to = "../src/types/rust/denom.ts"))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub enum Denom {
|
||||
Major,
|
||||
Minor,
|
||||
}
|
||||
|
||||
impl FromStr for Denom {
|
||||
type Err = BackendError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Denom, BackendError> {
|
||||
let s = s.to_lowercase();
|
||||
for network in Network::iter() {
|
||||
let denom = network.denom();
|
||||
if s == denom.to_lowercase() || s == "minor" {
|
||||
return Ok(Denom::Minor);
|
||||
} else if s == denom[1..].to_lowercase() || s == "major" {
|
||||
return Ok(Denom::Major);
|
||||
}
|
||||
}
|
||||
Err(BackendError::InvalidDenom(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<CosmosDenom> for Denom {
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(value: CosmosDenom) -> Result<Self, Self::Error> {
|
||||
Denom::from_str(&value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/coin.ts"))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct Coin {
|
||||
amount: String,
|
||||
denom: Denom,
|
||||
}
|
||||
|
||||
impl Coin {
|
||||
#[allow(unused)]
|
||||
pub fn major<T: ToString>(amount: T) -> Coin {
|
||||
Coin {
|
||||
amount: amount.to_string(),
|
||||
denom: Denom::Major,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn minor<T: ToString>(amount: T) -> Coin {
|
||||
Coin {
|
||||
amount: amount.to_string(),
|
||||
denom: Denom::Minor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new<T: ToString>(amount: T, denom: &Denom) -> Coin {
|
||||
Coin {
|
||||
amount: amount.to_string(),
|
||||
denom: denom.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_major(&self) -> Coin {
|
||||
match self.denom {
|
||||
Denom::Major => self.clone(),
|
||||
Denom::Minor => Coin {
|
||||
amount: (self.amount.parse::<f64>().unwrap() / MINOR_IN_MAJOR).to_string(),
|
||||
denom: Denom::Major,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_minor(&self) -> Coin {
|
||||
match self.denom {
|
||||
Denom::Minor => self.clone(),
|
||||
Denom::Major => Coin {
|
||||
amount: (self.amount.parse::<f64>().unwrap() * MINOR_IN_MAJOR).to_string(),
|
||||
denom: Denom::Minor,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn amount(&self) -> String {
|
||||
self.amount.clone()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn denom(&self) -> Denom {
|
||||
self.denom.clone()
|
||||
}
|
||||
|
||||
// Helper function that returns the local denom in terms of the specified network denom.
|
||||
fn denom_as_string(&self, network_denom: &str) -> Result<String, BackendError> {
|
||||
// Currently there is the widespread assumption that network denomination is always in
|
||||
// `Denom::Minor`, and starts with 'u'.
|
||||
let network_denom = network_denom.to_owned();
|
||||
if !network_denom.starts_with('u') {
|
||||
return Err(BackendError::InvalidNetworkDenom(network_denom));
|
||||
}
|
||||
|
||||
Ok(match &self.denom {
|
||||
Denom::Minor => network_denom,
|
||||
Denom::Major => network_denom[1..].to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_backend_coin(self, network_denom: &str) -> Result<BackendCoin, BackendError> {
|
||||
Ok(BackendCoin::new(
|
||||
self.amount.parse()?,
|
||||
self.denom_as_string(network_denom)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BackendCoin> for Coin {
|
||||
fn from(c: BackendCoin) -> Self {
|
||||
Coin {
|
||||
amount: c.amount.to_string(),
|
||||
denom: Denom::from_str(c.denom.as_ref()).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CosmosCoin> for Coin {
|
||||
fn from(c: CosmosCoin) -> Coin {
|
||||
Coin {
|
||||
amount: c.amount.to_string(),
|
||||
denom: Denom::from_str(c.denom.as_ref()).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CosmWasmCoin> for Coin {
|
||||
fn from(c: CosmWasmCoin) -> Coin {
|
||||
Coin {
|
||||
amount: c.amount.to_string(),
|
||||
denom: Denom::from_str(&c.denom).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::error::BackendError;
|
||||
use serde_json::json;
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn json_to_coin() {
|
||||
let minor = json!({
|
||||
"amount": "1",
|
||||
"denom": "Minor"
|
||||
});
|
||||
|
||||
let major = json!({
|
||||
"amount": "1",
|
||||
"denom": "Major"
|
||||
});
|
||||
|
||||
let test_minor_coin = Coin::minor("1");
|
||||
let test_major_coin = Coin::major("1");
|
||||
|
||||
let minor_coin = serde_json::from_value::<Coin>(minor).unwrap();
|
||||
let major_coin = serde_json::from_value::<Coin>(major).unwrap();
|
||||
|
||||
assert_eq!(minor_coin, test_minor_coin);
|
||||
assert_eq!(major_coin, test_major_coin);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn denom_from_str() {
|
||||
assert_eq!(Denom::from_str("unym").unwrap(), Denom::Minor);
|
||||
assert_eq!(Denom::from_str("nym").unwrap(), Denom::Major);
|
||||
assert_eq!(Denom::from_str("minor").unwrap(), Denom::Minor);
|
||||
assert_eq!(Denom::from_str("major").unwrap(), Denom::Major);
|
||||
|
||||
assert!(matches!(
|
||||
Denom::from_str("foo").unwrap_err(),
|
||||
BackendError::InvalidDenom { .. },
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn denom_conversions() {
|
||||
let minor = Coin::minor("1");
|
||||
let major = minor.to_major();
|
||||
|
||||
assert_eq!(major, Coin::major("0.000001"));
|
||||
|
||||
let minor = major.to_minor();
|
||||
assert_eq!(minor, Coin::minor("1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn network_denom_is_assumed_to_be_in_minor_denom() {
|
||||
let network_denom = "nym";
|
||||
assert!(matches!(
|
||||
Coin::minor("42")
|
||||
.denom_as_string(network_denom)
|
||||
.unwrap_err(),
|
||||
BackendError::InvalidNetworkDenom { .. }
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_denom_to_interpreted_using_network_denom() {
|
||||
let network_denom = "unym";
|
||||
assert_eq!(
|
||||
Coin::minor("42").denom_as_string(network_denom).unwrap(),
|
||||
"unym",
|
||||
);
|
||||
assert_eq!(
|
||||
Coin::major("42").denom_as_string(network_denom).unwrap(),
|
||||
"nym",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coin_to_coin_minor() {
|
||||
let network_denom = "unym";
|
||||
let coin = Coin::minor("42");
|
||||
|
||||
let backend_coin = coin.into_backend_coin(network_denom).unwrap();
|
||||
assert_eq!(backend_coin, BackendCoin::new(42, "unym"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coin_to_coin_major() {
|
||||
let network_denom = "unym";
|
||||
let coin = Coin::major("52");
|
||||
|
||||
let backend_coin = coin.into_backend_coin(network_denom).unwrap();
|
||||
assert_eq!(backend_coin, BackendCoin::new(52, "nym"));
|
||||
}
|
||||
|
||||
fn amounts() -> Vec<&'static str> {
|
||||
vec![
|
||||
"1",
|
||||
"10",
|
||||
"100",
|
||||
"1000",
|
||||
"10000",
|
||||
"100000",
|
||||
"10000000",
|
||||
"100000000",
|
||||
"1000000000",
|
||||
"10000000000",
|
||||
"100000000000",
|
||||
"1000000000000",
|
||||
"10000000000000",
|
||||
"100000000000000",
|
||||
"1000000000000000",
|
||||
"10000000000000000",
|
||||
"100000000000000000",
|
||||
"1000000000000000000",
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coin_to_backend() {
|
||||
let network_denom = "unym";
|
||||
for amount in amounts() {
|
||||
let coin = Coin::minor(amount);
|
||||
let backend_coin = coin.into_backend_coin(network_denom).unwrap();
|
||||
assert_eq!(
|
||||
backend_coin,
|
||||
BackendCoin::new(amount.parse::<u128>().unwrap(), "unym")
|
||||
);
|
||||
assert_eq!(Coin::try_from(backend_coin).unwrap(), Coin::minor(amount));
|
||||
|
||||
let coin = Coin::major(amount);
|
||||
let backend_coin = coin.into_backend_coin(network_denom).unwrap();
|
||||
assert_eq!(
|
||||
backend_coin,
|
||||
BackendCoin::new(amount.parse::<u128>().unwrap(), "nym")
|
||||
);
|
||||
assert_eq!(Coin::try_from(backend_coin).unwrap(), Coin::major(amount));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,26 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::network_config;
|
||||
use crate::platform_constants::{CONFIG_DIR_NAME, CONFIG_FILENAME};
|
||||
use crate::{error::BackendError, network::Network as WalletNetwork};
|
||||
use config::defaults::all::Network;
|
||||
use config::defaults::{all::SupportedNetworks, ValidatorDetails};
|
||||
use core::fmt;
|
||||
use itertools::Itertools;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::{fs, io, path::PathBuf};
|
||||
|
||||
use itertools::Itertools;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::IntoEnumIterator;
|
||||
use url::Url;
|
||||
use validator_client::nymd::AccountId as CosmosAccountId;
|
||||
|
||||
use config::defaults::all::Network;
|
||||
use config::defaults::{all::SupportedNetworks, ValidatorDetails};
|
||||
use nym_wallet_types::network::Network as WalletNetwork;
|
||||
use nym_wallet_types::network_config;
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::platform_constants::{CONFIG_DIR_NAME, CONFIG_FILENAME};
|
||||
|
||||
pub const REMOTE_SOURCE_OF_VALIDATOR_URLS: &str =
|
||||
"https://nymtech.net/.wellknown/wallet/validators.json";
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use nym_types::error::TypesError;
|
||||
use nym_wallet_types::network::Network;
|
||||
use serde::{Serialize, Serializer};
|
||||
use std::io;
|
||||
use std::num::ParseIntError;
|
||||
@@ -7,6 +9,11 @@ use validator_client::{nymd::error::NymdError, ValidatorClientError};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BackendError {
|
||||
#[error("{source}")]
|
||||
TypesError {
|
||||
#[from]
|
||||
source: TypesError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
Bip39Error {
|
||||
#[from]
|
||||
@@ -70,16 +77,10 @@ pub enum BackendError {
|
||||
ClientNotInitialized,
|
||||
#[error("No balance available for address {0}")]
|
||||
NoBalance(String),
|
||||
#[error("{0} is not a valid denomination string")]
|
||||
InvalidDenom(String),
|
||||
#[error("{0} is not a valid network denomination string")]
|
||||
InvalidNetworkDenom(String),
|
||||
#[error("The provided network is not supported (yet)")]
|
||||
NetworkNotSupported(config::defaults::all::Network),
|
||||
#[error("Could not access the local data storage directory")]
|
||||
UnknownStorageDirectory,
|
||||
#[error("No validator API URL configured")]
|
||||
NoValidatorApiUrlConfigured,
|
||||
#[error("The wallet file already exists")]
|
||||
WalletFileAlreadyExists,
|
||||
#[error("The wallet file is not found")]
|
||||
@@ -96,14 +97,18 @@ pub enum BackendError {
|
||||
WalletMnemonicAlreadyExistsInWalletLogin,
|
||||
#[error("Adding a different password to the wallet not currently supported")]
|
||||
WalletDifferentPasswordDetected,
|
||||
#[error("Unexpted mnemonic account for login")]
|
||||
#[error("Unexpected mnemonic account for login")]
|
||||
WalletUnexpectedMnemonicAccount,
|
||||
#[error("Unexpted multiple account entry for login")]
|
||||
WalletUnexpectedMultipleAccounts,
|
||||
// #[error("Unexpected multiple account entry for login")]
|
||||
// WalletUnexpectedMultipleAccounts,
|
||||
#[error("Failed to derive address from mnemonic")]
|
||||
FailedToDeriveAddress,
|
||||
#[error("{0}")]
|
||||
ValueParseError(#[from] ParseIntError),
|
||||
#[error("The provided coin has an unknown denomination - {0}")]
|
||||
UnknownCoinDenom(String),
|
||||
#[error("Network {network} doesn't have any associated registered coin denoms")]
|
||||
NoCoinsRegistered { network: Network },
|
||||
}
|
||||
|
||||
impl Serialize for BackendError {
|
||||
|
||||
@@ -3,19 +3,12 @@
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
use crate::menu::AddDefaultSubmenus;
|
||||
use crate::operations::{mixnet, simulate, validator_api, vesting};
|
||||
use crate::state::State;
|
||||
use mixnet_contract_common::{Gateway, MixNode};
|
||||
use std::sync::Arc;
|
||||
use tauri::Menu;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
mod coin;
|
||||
mod config;
|
||||
mod error;
|
||||
mod menu;
|
||||
mod network;
|
||||
mod network_config;
|
||||
mod operations;
|
||||
mod platform_constants;
|
||||
@@ -23,16 +16,23 @@ mod state;
|
||||
mod utils;
|
||||
mod wallet_storage;
|
||||
|
||||
use crate::menu::AddDefaultSubmenus;
|
||||
use crate::operations::mixnet;
|
||||
use crate::operations::simulate;
|
||||
use crate::operations::validator_api;
|
||||
use crate::operations::vesting;
|
||||
|
||||
use crate::state::WalletState;
|
||||
|
||||
fn main() {
|
||||
dotenv::dotenv().ok();
|
||||
setup_logging();
|
||||
|
||||
tauri::Builder::default()
|
||||
.manage(Arc::new(RwLock::new(State::default())))
|
||||
.manage(WalletState::default())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
mixnet::account::add_account_for_password,
|
||||
mixnet::account::connect_with_mnemonic,
|
||||
mixnet::account::create_new_account,
|
||||
mixnet::account::create_new_mnemonic,
|
||||
mixnet::account::create_password,
|
||||
mixnet::account::does_password_file_exist,
|
||||
@@ -59,7 +59,9 @@ fn main() {
|
||||
mixnet::delegate::delegate_to_mixnode,
|
||||
mixnet::delegate::get_delegator_rewards,
|
||||
mixnet::delegate::get_pending_delegation_events,
|
||||
mixnet::delegate::get_reverse_mix_delegations_paged,
|
||||
mixnet::delegate::get_delegation_summary,
|
||||
mixnet::delegate::get_all_pending_delegation_events,
|
||||
mixnet::delegate::get_all_mix_delegations,
|
||||
mixnet::delegate::undelegate_from_mixnode,
|
||||
mixnet::epoch::get_current_epoch,
|
||||
mixnet::rewards::claim_delegator_reward,
|
||||
@@ -76,8 +78,6 @@ fn main() {
|
||||
network_config::update_validator_urls,
|
||||
state::load_config_from_files,
|
||||
state::save_config_to_files,
|
||||
utils::major_to_minor,
|
||||
utils::minor_to_major,
|
||||
utils::owns_gateway,
|
||||
utils::owns_mixnode,
|
||||
utils::get_env,
|
||||
@@ -114,19 +114,18 @@ fn main() {
|
||||
vesting::queries::vesting_get_gateway_pledge,
|
||||
vesting::queries::vesting_get_mixnode_pledge,
|
||||
vesting::queries::vesting_start_time,
|
||||
// simulate endpoints
|
||||
simulate::admin::simulate_update_contract_settings,
|
||||
simulate::cosmos::simulate_send,
|
||||
simulate::mixnet::simulate_bond_gateway,
|
||||
simulate::mixnet::simulate_bond_mixnode,
|
||||
simulate::mixnet::simulate_unbond_gateway,
|
||||
simulate::mixnet::simulate_bond_mixnode,
|
||||
simulate::mixnet::simulate_unbond_mixnode,
|
||||
simulate::mixnet::simulate_update_mixnode,
|
||||
simulate::mixnet::simulate_delegate_to_mixnode,
|
||||
simulate::mixnet::simulate_undelegate_from_mixnode,
|
||||
simulate::cosmos::simulate_send,
|
||||
simulate::vesting::simulate_vesting_bond_gateway,
|
||||
simulate::vesting::simulate_vesting_bond_mixnode,
|
||||
simulate::vesting::simulate_vesting_unbond_gateway,
|
||||
simulate::vesting::simulate_vesting_bond_mixnode,
|
||||
simulate::vesting::simulate_vesting_unbond_mixnode,
|
||||
simulate::vesting::simulate_vesting_update_mixnode,
|
||||
simulate::vesting::simulate_withdraw_vested_coins,
|
||||
@@ -153,6 +152,10 @@ fn setup_logging() {
|
||||
log_builder.filter(None, log::LevelFilter::Info);
|
||||
}
|
||||
|
||||
if ::std::env::var("RUST_TRACE_OPERATIONS").is_ok() {
|
||||
log_builder.filter_module("nym_wallet::operations", log::LevelFilter::Trace);
|
||||
}
|
||||
|
||||
log_builder
|
||||
.filter_module("hyper", log::LevelFilter::Warn)
|
||||
.filter_module("tokio_reactor", log::LevelFilter::Warn)
|
||||
|
||||
@@ -2,56 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::network::Network as WalletNetwork;
|
||||
use crate::state::State;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fmt, sync::Arc};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
// When the UI queries validator urls we use this type
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/validatorurls.ts"))]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ValidatorUrls {
|
||||
pub urls: Vec<ValidatorUrl>,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/validatorurl.ts"))]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ValidatorUrl {
|
||||
pub url: String,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
// The type used when adding or removing validators, effectively the input.
|
||||
// NOTE: we should consider if we want to split this up
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/validatorurls.ts"))]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Validator {
|
||||
pub nymd_url: String,
|
||||
pub nymd_name: Option<String>,
|
||||
pub api_url: Option<String>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Validator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let nymd_url = format!("nymd_url: {}", self.nymd_url);
|
||||
let api_url = self
|
||||
.api_url
|
||||
.as_ref()
|
||||
.map(|api_url| format!(", api_url: {}", api_url))
|
||||
.unwrap_or_default();
|
||||
write!(f, "{nymd_url}{api_url}")
|
||||
}
|
||||
}
|
||||
use crate::state::WalletState;
|
||||
use nym_wallet_types::network::Network as WalletNetwork;
|
||||
use nym_wallet_types::network_config::{Validator, ValidatorUrl, ValidatorUrls};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_validator_nymd_urls(
|
||||
network: WalletNetwork,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<ValidatorUrls, BackendError> {
|
||||
let state = state.read().await;
|
||||
let urls: Vec<ValidatorUrl> = state.get_nymd_urls(network).collect();
|
||||
@@ -61,7 +19,7 @@ pub async fn get_validator_nymd_urls(
|
||||
#[tauri::command]
|
||||
pub async fn get_validator_api_urls(
|
||||
network: WalletNetwork,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<ValidatorUrls, BackendError> {
|
||||
let state = state.read().await;
|
||||
let urls: Vec<ValidatorUrl> = state.get_api_urls(network).collect();
|
||||
@@ -72,7 +30,7 @@ pub async fn get_validator_api_urls(
|
||||
pub async fn select_validator_nymd_url(
|
||||
url: &str,
|
||||
network: WalletNetwork,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::debug!("Selecting new validator nymd_url for {network}: {url}");
|
||||
state
|
||||
@@ -86,7 +44,7 @@ pub async fn select_validator_nymd_url(
|
||||
pub async fn select_validator_api_url(
|
||||
url: &str,
|
||||
network: WalletNetwork,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::debug!("Selecting new validator api_url for {network}: {url}");
|
||||
state.write().await.select_validator_api_url(url, network)?;
|
||||
@@ -97,7 +55,7 @@ pub async fn select_validator_api_url(
|
||||
pub async fn add_validator(
|
||||
validator: Validator,
|
||||
network: WalletNetwork,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::debug!("Add validator for {network}: {validator}");
|
||||
let url = validator.try_into()?;
|
||||
@@ -109,7 +67,7 @@ pub async fn add_validator(
|
||||
pub async fn remove_validator(
|
||||
validator: Validator,
|
||||
network: WalletNetwork,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::debug!("Remove validator for {network}: {validator}");
|
||||
let url = validator.try_into()?;
|
||||
@@ -120,7 +78,7 @@ pub async fn remove_validator(
|
||||
// Update the list of validators by fecthing additional ones remotely. If it fails, just ignore.
|
||||
#[tauri::command]
|
||||
pub async fn update_validator_urls(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
let mut w_state = state.write().await;
|
||||
let _r = w_state.fetch_updated_validator_urls().await;
|
||||
|
||||
@@ -1,115 +1,51 @@
|
||||
use crate::coin::{Coin, Denom};
|
||||
use crate::config::{Config, CUSTOM_SIMULATED_GAS_MULTIPLIER};
|
||||
use crate::error::BackendError;
|
||||
use crate::network::Network as WalletNetwork;
|
||||
use crate::network_config;
|
||||
use crate::nymd_client;
|
||||
use crate::state::{State, WalletAccountIds};
|
||||
use crate::state::{WalletAccountIds, WalletState};
|
||||
use crate::wallet_storage::{self, DEFAULT_LOGIN_ID};
|
||||
|
||||
use bip39::{Language, Mnemonic};
|
||||
use config::defaults::all::Network;
|
||||
use config::defaults::COSMOS_DERIVATION_PATH;
|
||||
use cosmrs::bip32::DerivationPath;
|
||||
use itertools::Itertools;
|
||||
use nym_types::account::{Account, AccountEntry, Balance};
|
||||
use nym_wallet_types::network::Network as WalletNetwork;
|
||||
use rand::seq::SliceRandom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use strum::IntoEnumIterator;
|
||||
use tokio::sync::RwLock;
|
||||
use url::Url;
|
||||
use validator_client::nymd::bip32::DerivationPath;
|
||||
use validator_client::nymd::wallet::{AccountData, DirectSecp256k1HdWallet};
|
||||
use validator_client::nymd::{AccountId as CosmosAccountId, SigningNymdClient};
|
||||
use validator_client::Client;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/account.ts"))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Account {
|
||||
contract_address: String,
|
||||
client_address: String,
|
||||
denom: Denom,
|
||||
}
|
||||
|
||||
impl Account {
|
||||
pub fn new(contract_address: String, client_address: String, denom: Denom) -> Self {
|
||||
Account {
|
||||
contract_address,
|
||||
client_address,
|
||||
denom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/createdaccount.ts"))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CreatedAccount {
|
||||
account: Account,
|
||||
mnemonic: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/createdaccount.ts"))]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AccountEntry {
|
||||
id: String,
|
||||
address: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/balance.ts"))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Balance {
|
||||
coin: Coin,
|
||||
printable_balance: String,
|
||||
}
|
||||
use validator_client::{nymd::SigningNymdClient, Client};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn connect_with_mnemonic(
|
||||
mnemonic: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Account, BackendError> {
|
||||
let mnemonic = Mnemonic::from_str(&mnemonic)?;
|
||||
_connect_with_mnemonic(mnemonic, state).await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_balance(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Balance, BackendError> {
|
||||
let denom = state.read().await.current_network().denom().to_owned();
|
||||
match nymd_client!(state)
|
||||
.get_balance(nymd_client!(state).address(), denom.parse()?)
|
||||
.await
|
||||
{
|
||||
Ok(Some(coin)) => {
|
||||
let coin = Coin::new(&coin.amount.to_string(), &Denom::from_str(&coin.denom)?);
|
||||
Ok(Balance {
|
||||
coin: coin.clone(),
|
||||
// haha, that's so junky : )
|
||||
printable_balance: format!("{} {}", coin.to_major().amount(), &denom[1..]),
|
||||
})
|
||||
}
|
||||
Ok(None) => Err(BackendError::NoBalance(
|
||||
nymd_client!(state).address().to_string(),
|
||||
)),
|
||||
Err(e) => Err(BackendError::from(e)),
|
||||
}
|
||||
}
|
||||
pub async fn get_balance(state: tauri::State<'_, WalletState>) -> Result<Balance, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let address = client.nymd.address();
|
||||
let network = guard.current_network();
|
||||
let base_mix_denom = network.base_mix_denom();
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_new_account(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<CreatedAccount, BackendError> {
|
||||
let rand_mnemonic = random_mnemonic();
|
||||
let account = connect_with_mnemonic(rand_mnemonic.to_string(), state).await?;
|
||||
Ok(CreatedAccount {
|
||||
account,
|
||||
mnemonic: rand_mnemonic.to_string(),
|
||||
})
|
||||
match client
|
||||
.nymd
|
||||
.get_balance(address, base_mix_denom.to_string())
|
||||
.await?
|
||||
{
|
||||
Some(coin) => {
|
||||
let amount = guard.attempt_convert_to_display_dec_coin(coin)?;
|
||||
Ok(Balance::new(amount))
|
||||
}
|
||||
None => Err(BackendError::NoBalance(address.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -124,18 +60,18 @@ pub fn validate_mnemonic(mnemonic: &str) -> bool {
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn switch_network(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
network: WalletNetwork,
|
||||
) -> Result<Account, BackendError> {
|
||||
let account = {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client(network)?;
|
||||
let denom = network.denom();
|
||||
let denom = network.base_mix_denom();
|
||||
|
||||
Account::new(
|
||||
client.nymd.mixnet_contract_address().to_string(),
|
||||
client.nymd.address().to_string(),
|
||||
denom.parse()?,
|
||||
denom.into(),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -146,7 +82,7 @@ pub async fn switch_network(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn logout(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<(), BackendError> {
|
||||
pub async fn logout(state: tauri::State<'_, WalletState>) -> Result<(), BackendError> {
|
||||
state.write().await.logout();
|
||||
Ok(())
|
||||
}
|
||||
@@ -158,7 +94,7 @@ fn random_mnemonic() -> Mnemonic {
|
||||
|
||||
async fn _connect_with_mnemonic(
|
||||
mnemonic: Mnemonic,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Account, BackendError> {
|
||||
{
|
||||
let mut w_state = state.write().await;
|
||||
@@ -218,7 +154,7 @@ async fn _connect_with_mnemonic(
|
||||
Some(client) => Ok(Account::new(
|
||||
client.nymd.mixnet_contract_address().to_string(),
|
||||
client.nymd.address().to_string(),
|
||||
default_network.denom().parse()?,
|
||||
default_network.base_mix_denom().into(),
|
||||
)),
|
||||
None => Err(BackendError::NetworkNotSupported(
|
||||
config::defaults::DEFAULT_NETWORK,
|
||||
@@ -234,6 +170,7 @@ async fn _connect_with_mnemonic(
|
||||
let network: WalletNetwork = client.network.into();
|
||||
let mut w_state = state.write().await;
|
||||
w_state.add_client(network, client);
|
||||
w_state.register_default_denoms(network);
|
||||
}
|
||||
|
||||
account_for_default_network
|
||||
@@ -378,7 +315,7 @@ pub fn create_password(mnemonic: &str, password: String) -> Result<(), BackendEr
|
||||
#[tauri::command]
|
||||
pub async fn sign_in_with_password(
|
||||
password: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Account, BackendError> {
|
||||
log::info!("Signing in with password");
|
||||
|
||||
@@ -418,7 +355,7 @@ fn extract_first_mnemonic(
|
||||
pub async fn sign_in_with_password_and_account_id(
|
||||
account_id: &str,
|
||||
password: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Account, BackendError> {
|
||||
log::info!("Signing in with password");
|
||||
|
||||
@@ -465,9 +402,9 @@ pub async fn add_account_for_password(
|
||||
mnemonic: &str,
|
||||
password: &str,
|
||||
account_id: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<AccountEntry, BackendError> {
|
||||
log::info!("Adding account: {account_id}");
|
||||
log::info!("Adding account for the current password: {account_id}");
|
||||
let mnemonic = Mnemonic::from_str(mnemonic)?;
|
||||
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
|
||||
// Currently we only support a single, default, login id in the wallet
|
||||
@@ -507,7 +444,7 @@ pub async fn add_account_for_password(
|
||||
async fn set_state_with_all_accounts(
|
||||
stored_login: wallet_storage::StoredLogin,
|
||||
first_id_when_converting: wallet_storage::AccountId,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::trace!("Set state with accounts:");
|
||||
let all_accounts: Vec<_> = stored_login
|
||||
@@ -523,7 +460,7 @@ async fn set_state_with_all_accounts(
|
||||
.iter()
|
||||
.map(|account| {
|
||||
let mnemonic = account.mnemonic();
|
||||
let addresses: HashMap<WalletNetwork, CosmosAccountId> = WalletNetwork::iter()
|
||||
let addresses: HashMap<WalletNetwork, cosmrs::AccountId> = WalletNetwork::iter()
|
||||
.map(|network| {
|
||||
let config_network: Network = network.into();
|
||||
(
|
||||
@@ -548,7 +485,7 @@ async fn set_state_with_all_accounts(
|
||||
pub async fn remove_account_for_password(
|
||||
password: &str,
|
||||
account_id: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
log::info!("Removing account: {account_id}");
|
||||
// Currently we only support a single, default, id in the wallet
|
||||
@@ -568,7 +505,7 @@ pub async fn remove_account_for_password(
|
||||
fn derive_address(
|
||||
mnemonic: bip39::Mnemonic,
|
||||
prefix: &str,
|
||||
) -> Result<CosmosAccountId, BackendError> {
|
||||
) -> Result<cosmrs::AccountId, BackendError> {
|
||||
DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic)?
|
||||
.try_derive_accounts()?
|
||||
.first()
|
||||
@@ -579,7 +516,7 @@ fn derive_address(
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_accounts(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Vec<AccountEntry>, BackendError> {
|
||||
log::trace!("Listing accounts");
|
||||
let state = state.read().await;
|
||||
@@ -637,8 +574,6 @@ fn _show_mnemonic_for_account_in_password(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::wallet_storage::{
|
||||
@@ -646,6 +581,8 @@ mod tests {
|
||||
account_data::{MnemonicAccount, WalletAccount},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
// This decryptes a stored wallet file using the same procedure as when signing in. Most tests
|
||||
// related to the encryped wallet storage is in `wallet_storage`.
|
||||
#[test]
|
||||
|
||||
@@ -1,64 +1,36 @@
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Uint128;
|
||||
use crate::state::WalletState;
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use nym_wallet_types::admin::TauriContractStateParams;
|
||||
use std::convert::TryInto;
|
||||
use validator_client::nymd::Fee;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/stateparams.ts"))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct TauriContractStateParams {
|
||||
minimum_mixnode_pledge: String,
|
||||
minimum_gateway_pledge: String,
|
||||
mixnode_rewarded_set_size: u32,
|
||||
mixnode_active_set_size: u32,
|
||||
}
|
||||
|
||||
impl From<ContractStateParams> for TauriContractStateParams {
|
||||
fn from(p: ContractStateParams) -> TauriContractStateParams {
|
||||
TauriContractStateParams {
|
||||
minimum_mixnode_pledge: p.minimum_mixnode_pledge.to_string(),
|
||||
minimum_gateway_pledge: p.minimum_gateway_pledge.to_string(),
|
||||
mixnode_rewarded_set_size: p.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(p: TauriContractStateParams) -> Result<ContractStateParams, Self::Error> {
|
||||
Ok(ContractStateParams {
|
||||
minimum_mixnode_pledge: Uint128::try_from(p.minimum_mixnode_pledge.as_str())?,
|
||||
minimum_gateway_pledge: Uint128::try_from(p.minimum_gateway_pledge.as_str())?,
|
||||
mixnode_rewarded_set_size: p.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_contract_settings(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TauriContractStateParams, BackendError> {
|
||||
Ok(nymd_client!(state).get_contract_settings().await?.into())
|
||||
log::info!(">>> Getting contract settings");
|
||||
let res = nymd_client!(state).get_contract_settings().await?.into();
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_contract_settings(
|
||||
params: TauriContractStateParams,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TauriContractStateParams, BackendError> {
|
||||
let mixnet_contract_settings_params: ContractStateParams = params.try_into()?;
|
||||
log::info!(
|
||||
">>> Updating contract settings: {:?}",
|
||||
mixnet_contract_settings_params
|
||||
);
|
||||
nymd_client!(state)
|
||||
.update_contract_settings(mixnet_contract_settings_params.clone(), fee)
|
||||
.await?;
|
||||
Ok(mixnet_contract_settings_params.into())
|
||||
let res = mixnet_contract_settings_params.into();
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -1,98 +1,200 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::state::WalletState;
|
||||
use crate::{Gateway, MixNode};
|
||||
use cosmwasm_std::Uint128;
|
||||
use mixnet_contract_common::{GatewayBond, MixNodeBond};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::Fee;
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::gateway::GatewayBond;
|
||||
use nym_types::mixnode::MixNodeBond;
|
||||
use nym_types::transaction::TransactionExecuteResult;
|
||||
use validator_client::nymd::{Coin, Fee};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
pledge: DecCoin,
|
||||
owner_signature: String,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
let pledge = pledge.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.bond_gateway(gateway, owner_signature, pledge, fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Bond gateway: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}",
|
||||
gateway.identity_key,
|
||||
pledge,
|
||||
pledge_base,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.bond_gateway(gateway, owner_signature, pledge_base, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_gateway(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state).unbond_gateway(fee).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_mixnode(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state).unbond_mixnode(fee).await?;
|
||||
Ok(())
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(">>> Unbond gateway, fee = {:?}", fee);
|
||||
let res = guard.current_client()?.nymd.unbond_gateway(fee).await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
pledge: DecCoin,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
let pledge = pledge.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.bond_mixnode(mixnode, owner_signature, pledge, fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Bond mixnode: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}",
|
||||
mixnode.identity_key,
|
||||
pledge,
|
||||
pledge_base,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.bond_mixnode(mixnode, owner_signature, pledge_base, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_mixnode(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(">>> Unbond mixnode, fee = {:?}", fee);
|
||||
let res = guard.current_client()?.nymd.unbond_mixnode(fee).await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_mixnode(
|
||||
profit_margin_percent: u8,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Update mixnode: profit_margin_percent = {}, fee {:?}",
|
||||
profit_margin_percent,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.update_mixnode_config(profit_margin_percent, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn mixnode_bond_details(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Option<MixNodeBond>, BackendError> {
|
||||
log::info!(">>> Get mixnode bond details");
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let bond = client.nymd.owns_mixnode(client.nymd.address()).await?;
|
||||
Ok(bond)
|
||||
let res = bond
|
||||
.map(|bond| {
|
||||
guard
|
||||
.registered_coins()
|
||||
.map(|reg| MixNodeBond::from_mixnet_contract_mixnode_bond(bond, reg))
|
||||
})
|
||||
.transpose()?
|
||||
.transpose()?;
|
||||
log::info!(
|
||||
"<<< identity_key = {:?}",
|
||||
res.as_ref().map(|r| r.mix_node.identity_key.to_string())
|
||||
);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn gateway_bond_details(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Option<GatewayBond>, BackendError> {
|
||||
log::info!(">>> Get gateway bond details");
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let bond = client.nymd.owns_gateway(client.nymd.address()).await?;
|
||||
Ok(bond)
|
||||
let res = bond
|
||||
.map(|bond| {
|
||||
guard
|
||||
.registered_coins()
|
||||
.map(|reg| GatewayBond::from_mixnet_contract_gateway_bond(bond, reg))
|
||||
})
|
||||
.transpose()?
|
||||
.transpose()?;
|
||||
|
||||
log::info!(
|
||||
"<<< identity_key = {:?}",
|
||||
res.as_ref().map(|r| r.gateway.identity_key.to_string())
|
||||
);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_operator_rewards(
|
||||
address: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Uint128, BackendError> {
|
||||
Ok(nymd_client!(state).get_operator_rewards(address).await?)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<DecCoin, BackendError> {
|
||||
log::info!(">>> Get operator rewards for {}", address);
|
||||
let guard = state.read().await;
|
||||
let network = guard.current_network();
|
||||
let denom = network.base_mix_denom();
|
||||
let reward_amount = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.get_operator_rewards(address)
|
||||
.await?;
|
||||
let base_coin = Coin::new(reward_amount.u128(), denom);
|
||||
let display_coin: DecCoin = guard.attempt_convert_to_display_dec_coin(base_coin.clone())?;
|
||||
log::info!(
|
||||
"<<< rewards_base = {}, rewards_display = {}",
|
||||
base_coin,
|
||||
display_coin
|
||||
);
|
||||
Ok(display_coin)
|
||||
}
|
||||
|
||||
@@ -1,68 +1,315 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::utils::DelegationEvent;
|
||||
use crate::utils::DelegationResult;
|
||||
use cosmwasm_std::Uint128;
|
||||
use mixnet_contract_common::{IdentityKey, PagedDelegatorDelegationsResponse};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::Fee;
|
||||
use crate::state::WalletState;
|
||||
use crate::vesting::delegate::get_pending_vesting_delegation_events;
|
||||
use crate::{api_client, nymd_client};
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::delegation::{
|
||||
Delegation, DelegationEvent, DelegationRecord, DelegationWithEverything,
|
||||
DelegationsSummaryResponse,
|
||||
};
|
||||
use nym_types::transaction::TransactionExecuteResult;
|
||||
use std::collections::HashMap;
|
||||
use validator_client::nymd::{Coin, Fee};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_pending_delegation_events(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Vec<DelegationEvent>, BackendError> {
|
||||
Ok(nymd_client!(state)
|
||||
.get_pending_delegation_events(nymd_client!(state).address().to_string(), None)
|
||||
.await?
|
||||
log::info!(">>> Get pending delegation events");
|
||||
let guard = state.read().await;
|
||||
let reg = guard.registered_coins()?;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let events = client
|
||||
.nymd
|
||||
.get_pending_delegation_events(client.nymd.address().to_string(), None)
|
||||
.await?;
|
||||
log::info!("<<< {} pending delegation events", events.len());
|
||||
log::trace!("<<< pending delegation events = {:?}", events);
|
||||
|
||||
Ok(events
|
||||
.into_iter()
|
||||
.map(|delegation_event| delegation_event.into())
|
||||
.collect::<Vec<DelegationEvent>>())
|
||||
.map(|event| DelegationEvent::from_mixnet_contract(event, reg))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
amount: DecCoin,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
let delegation = amount.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.delegate_to_mixnode(identity, delegation.clone(), fee)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
nymd_client!(state).address().as_ref(),
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let delegation_base = guard.attempt_convert_to_base_coin(amount.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Delegate to mixnode: identity_key = {}, display_amount = {}, base_amount = {}, fee = {:?}",
|
||||
identity,
|
||||
Some(delegation.into()),
|
||||
))
|
||||
amount,
|
||||
delegation_base,
|
||||
fee,
|
||||
);
|
||||
let res = nymd_client!(state)
|
||||
.delegate_to_mixnode(identity, delegation_base, fee)
|
||||
.await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
nymd_client!(state)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Undelegate from mixnode: identity_key = {}, fee = {:?}",
|
||||
identity,
|
||||
fee
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.remove_mixnode_delegation(identity, fee)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
nymd_client!(state).address().as_ref(),
|
||||
identity,
|
||||
None,
|
||||
))
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
struct DelegationWithHistory {
|
||||
pub delegation: Delegation,
|
||||
pub amount_sum: DecCoin,
|
||||
pub history: Vec<DelegationRecord>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_reverse_mix_delegations_paged(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<PagedDelegatorDelegationsResponse, BackendError> {
|
||||
Ok(nymd_client!(state)
|
||||
.get_delegator_delegations_paged(nymd_client!(state).address().to_string(), None, None)
|
||||
.await?)
|
||||
pub async fn get_all_mix_delegations(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Vec<DelegationWithEverything>, BackendError> {
|
||||
log::info!(">>> Get all mixnode delegations");
|
||||
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
let reg = guard.registered_coins()?;
|
||||
|
||||
// TODO: add endpoint to validator API to get a single mix node bond
|
||||
let mixnodes = client.validator_api.get_mixnodes().await?;
|
||||
|
||||
let address = client.nymd.address();
|
||||
let network = guard.current_network();
|
||||
let display_mix_denom = network.display_mix_denom();
|
||||
let base_mix_denom = network.base_mix_denom();
|
||||
|
||||
log::info!(" >>> Get delegations");
|
||||
let delegations = client.get_all_delegator_delegations(address).await?;
|
||||
log::info!(" <<< {} delegations", delegations.len());
|
||||
|
||||
// first get pending events from the mixnet contract (operations made with unlocked tokens)
|
||||
let mut pending_events_for_account = get_pending_delegation_events(state.clone()).await?;
|
||||
|
||||
// then get pending events from the vesting contract (operations made with locked tokens)
|
||||
let pending_vesting_events = get_pending_vesting_delegation_events(state.clone()).await?;
|
||||
for event in pending_vesting_events {
|
||||
pending_events_for_account.push(event);
|
||||
}
|
||||
|
||||
log::info!(
|
||||
" <<< {} pending delegation events for account",
|
||||
pending_events_for_account.len()
|
||||
);
|
||||
|
||||
let mut map: HashMap<String, DelegationWithHistory> = HashMap::new();
|
||||
|
||||
for pending_event in &pending_events_for_account {
|
||||
if delegations
|
||||
.iter()
|
||||
.any(|d| d.node_identity == pending_event.node_identity)
|
||||
{
|
||||
let amount = pending_event
|
||||
.amount
|
||||
.clone()
|
||||
.unwrap_or_else(|| DecCoin::zero(display_mix_denom));
|
||||
let delegation = DelegationWithHistory {
|
||||
delegation: Delegation {
|
||||
amount: amount.clone(),
|
||||
node_identity: pending_event.node_identity.clone(),
|
||||
proxy: None, // TODO: ask @MS about delegations via vesting contract => surely we'd have proxy there?
|
||||
owner: pending_event.address.clone(),
|
||||
block_height: pending_event.block_height,
|
||||
},
|
||||
amount_sum: amount,
|
||||
history: vec![],
|
||||
};
|
||||
map.insert(delegation.delegation.node_identity.clone(), delegation);
|
||||
}
|
||||
}
|
||||
|
||||
for d in delegations {
|
||||
// create record of delegation
|
||||
let delegated_on_iso_datetime = client
|
||||
.nymd
|
||||
.get_block_timestamp(Some(d.block_height as u32))
|
||||
.await?
|
||||
.to_rfc3339();
|
||||
let amount = guard.attempt_convert_to_display_dec_coin(d.amount.clone().into())?;
|
||||
|
||||
let record = DelegationRecord {
|
||||
amount: amount.clone(),
|
||||
block_height: d.block_height,
|
||||
delegated_on_iso_datetime,
|
||||
};
|
||||
|
||||
let entry = map
|
||||
.entry(d.node_identity.clone())
|
||||
.or_insert(DelegationWithHistory {
|
||||
delegation: Delegation::from_mixnet_contract(d, reg)?,
|
||||
history: vec![],
|
||||
amount_sum: DecCoin::zero(display_mix_denom),
|
||||
});
|
||||
|
||||
debug_assert_eq!(entry.amount_sum.denom, amount.denom);
|
||||
|
||||
entry.history.push(record);
|
||||
entry.amount_sum.amount += amount.amount;
|
||||
}
|
||||
|
||||
let mut with_everything: Vec<DelegationWithEverything> = vec![];
|
||||
|
||||
for item in map {
|
||||
let d = item.1.delegation;
|
||||
let history = item.1.history;
|
||||
let Delegation {
|
||||
owner,
|
||||
node_identity,
|
||||
amount,
|
||||
block_height,
|
||||
proxy,
|
||||
} = d;
|
||||
|
||||
log::trace!(
|
||||
" --- Delegation: node_identity = {}, amount = {}",
|
||||
node_identity,
|
||||
amount
|
||||
);
|
||||
|
||||
let mixnode = mixnodes
|
||||
.iter()
|
||||
.find(|m| m.mix_node.identity_key == node_identity);
|
||||
|
||||
let pledge_amount = mixnode
|
||||
.map(|m| guard.attempt_convert_to_display_dec_coin(m.pledge_amount.clone().into()))
|
||||
.transpose()?;
|
||||
|
||||
let total_delegation = mixnode
|
||||
.map(|m| guard.attempt_convert_to_display_dec_coin(m.total_delegation.clone().into()))
|
||||
.transpose()?;
|
||||
|
||||
let profit_margin_percent: Option<u8> = mixnode.map(|m| m.mix_node.profit_margin_percent);
|
||||
|
||||
log::trace!(" >>> Get accumulated rewards: address = {}", address);
|
||||
let accumulated_rewards = match client
|
||||
.nymd
|
||||
.get_delegator_rewards(address.to_string(), node_identity.clone(), proxy.clone())
|
||||
.await
|
||||
{
|
||||
Ok(rewards) => {
|
||||
let reward = Coin::new(rewards.u128(), base_mix_denom);
|
||||
let amount = guard.attempt_convert_to_display_dec_coin(reward)?;
|
||||
log::trace!(" <<< rewards = {}, amount = {}", rewards, amount);
|
||||
Some(amount)
|
||||
}
|
||||
Err(_) => {
|
||||
log::trace!(" <<< no rewards waiting");
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let pending_events =
|
||||
filter_pending_events(&node_identity, pending_events_for_account.clone());
|
||||
log::trace!(
|
||||
" --- pending events for mixnode = {}",
|
||||
pending_events.len()
|
||||
);
|
||||
|
||||
log::trace!(
|
||||
" >>> Get stake saturation: node_identity = {}",
|
||||
node_identity
|
||||
);
|
||||
let stake_saturation = api_client!(state)
|
||||
.get_mixnode_stake_saturation(&node_identity)
|
||||
.await
|
||||
.ok()
|
||||
.map(|r| r.saturation);
|
||||
log::trace!(" <<< {:?}", stake_saturation);
|
||||
|
||||
log::trace!(
|
||||
" >>> Get average uptime percentage: node_identity = {}",
|
||||
node_identity
|
||||
);
|
||||
let avg_uptime_percent = api_client!(state)
|
||||
.get_mixnode_avg_uptime(&node_identity)
|
||||
.await
|
||||
.ok()
|
||||
.map(|r| r.avg_uptime);
|
||||
log::trace!(" <<< {:?}", avg_uptime_percent);
|
||||
|
||||
log::trace!(
|
||||
" >>> Convert delegated on block height to timestamp: block_height = {}",
|
||||
d.block_height
|
||||
);
|
||||
let timestamp = nymd_client!(state)
|
||||
.get_block_timestamp(Some(d.block_height as u32))
|
||||
.await?;
|
||||
let delegated_on_iso_datetime = timestamp.to_rfc3339();
|
||||
log::trace!(
|
||||
" <<< timestamp = {:?}, delegated_on_iso_datetime = {:?}",
|
||||
timestamp,
|
||||
delegated_on_iso_datetime
|
||||
);
|
||||
|
||||
with_everything.push(DelegationWithEverything {
|
||||
owner: owner.to_string(),
|
||||
node_identity: node_identity.to_string(),
|
||||
amount: item.1.amount_sum,
|
||||
block_height,
|
||||
proxy: proxy.clone(),
|
||||
delegated_on_iso_datetime,
|
||||
stake_saturation,
|
||||
accumulated_rewards,
|
||||
profit_margin_percent,
|
||||
pledge_amount,
|
||||
avg_uptime_percent,
|
||||
total_delegation,
|
||||
pending_events,
|
||||
history,
|
||||
})
|
||||
}
|
||||
log::trace!("<<< {:?}", with_everything);
|
||||
|
||||
Ok(with_everything)
|
||||
}
|
||||
|
||||
fn filter_pending_events(
|
||||
node_identity: &str,
|
||||
pending_events: Vec<DelegationEvent>,
|
||||
) -> Vec<DelegationEvent> {
|
||||
pending_events
|
||||
.iter()
|
||||
.filter(|e| e.node_identity == node_identity)
|
||||
.cloned()
|
||||
.collect::<Vec<DelegationEvent>>()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -70,9 +317,83 @@ pub async fn get_delegator_rewards(
|
||||
address: String,
|
||||
mix_identity: IdentityKey,
|
||||
proxy: Option<String>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Uint128, BackendError> {
|
||||
Ok(nymd_client!(state)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<DecCoin, BackendError> {
|
||||
log::info!(
|
||||
">>> Get delegator rewards: mix_identity = {}, proxy = {:?}",
|
||||
mix_identity,
|
||||
proxy
|
||||
);
|
||||
let guard = state.read().await;
|
||||
let network = guard.current_network();
|
||||
let denom = network.base_mix_denom();
|
||||
let reward_amount = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.get_delegator_rewards(address, mix_identity, proxy)
|
||||
.await?)
|
||||
.await?;
|
||||
let base_coin = Coin::new(reward_amount.u128(), denom);
|
||||
let display_coin: DecCoin = guard.attempt_convert_to_display_dec_coin(base_coin.clone())?;
|
||||
|
||||
log::info!(
|
||||
"<<< rewards_base = {}, rewards_display = {}",
|
||||
base_coin,
|
||||
display_coin
|
||||
);
|
||||
Ok(display_coin)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_delegation_summary(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<DelegationsSummaryResponse, BackendError> {
|
||||
log::info!(">>> Get delegation summary");
|
||||
|
||||
let guard = state.read().await;
|
||||
let network = guard.current_network();
|
||||
let display_mix_denom = network.display_mix_denom();
|
||||
|
||||
let delegations = get_all_mix_delegations(state.clone()).await?;
|
||||
let mut total_delegations = DecCoin::zero(display_mix_denom);
|
||||
let mut total_rewards = DecCoin::zero(display_mix_denom);
|
||||
|
||||
for d in &delegations {
|
||||
debug_assert_eq!(d.amount.denom, display_mix_denom);
|
||||
total_delegations.amount += d.amount.amount;
|
||||
if let Some(rewards) = &d.accumulated_rewards {
|
||||
debug_assert_eq!(rewards.denom, display_mix_denom);
|
||||
total_rewards.amount += rewards.amount;
|
||||
}
|
||||
}
|
||||
log::info!(
|
||||
"<<< {} delegations, total_delegations = {}, total_rewards = {}",
|
||||
delegations.len(),
|
||||
total_delegations,
|
||||
total_rewards
|
||||
);
|
||||
log::trace!("<<< {:?}", delegations);
|
||||
|
||||
Ok(DelegationsSummaryResponse {
|
||||
delegations,
|
||||
total_delegations,
|
||||
total_rewards,
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_all_pending_delegation_events(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Vec<DelegationEvent>, BackendError> {
|
||||
log::info!(">>> Get all pending delegation events");
|
||||
|
||||
// get pending events from mixnet and vesting contract
|
||||
let mut pending_events_for_account = get_pending_delegation_events(state.clone()).await?;
|
||||
let pending_vesting_events = get_pending_vesting_delegation_events(state.clone()).await?;
|
||||
|
||||
// combine them
|
||||
for event in pending_vesting_events {
|
||||
pending_events_for_account.push(event);
|
||||
}
|
||||
|
||||
Ok(pending_events_for_account)
|
||||
}
|
||||
|
||||
@@ -1,36 +1,14 @@
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use mixnet_contract_common::Interval;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/epoch.ts"))]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct Epoch {
|
||||
id: u32,
|
||||
start: i64,
|
||||
end: i64,
|
||||
duration_seconds: u64,
|
||||
}
|
||||
|
||||
impl From<Interval> for Epoch {
|
||||
fn from(interval: Interval) -> Self {
|
||||
Self {
|
||||
id: interval.id(),
|
||||
start: interval.start_unix_timestamp(),
|
||||
end: interval.end_unix_timestamp(),
|
||||
duration_seconds: interval.length().as_secs(),
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::state::WalletState;
|
||||
use nym_wallet_types::epoch::Epoch;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_current_epoch(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Epoch, BackendError> {
|
||||
log::info!(">>> Get curren epoch");
|
||||
let interval = nymd_client!(state).get_current_epoch().await?;
|
||||
log::info!("<<< curren epoch = {}", interval);
|
||||
Ok(interval.into())
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::state::WalletState;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::Fee;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn claim_operator_reward(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state)
|
||||
.execute_claim_operator_reward(fee)
|
||||
@@ -20,7 +18,7 @@ pub async fn claim_operator_reward(
|
||||
#[tauri::command]
|
||||
pub async fn compound_operator_reward(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state)
|
||||
.execute_compound_operator_reward(fee)
|
||||
@@ -32,7 +30,7 @@ pub async fn compound_operator_reward(
|
||||
pub async fn claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state)
|
||||
.execute_claim_delegator_reward(mix_identity, fee)
|
||||
@@ -44,7 +42,7 @@ pub async fn claim_delegator_reward(
|
||||
pub async fn compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state)
|
||||
.execute_compound_delegator_reward(mix_identity, fee)
|
||||
|
||||
@@ -1,69 +1,43 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::state::WalletState;
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::transaction::{SendTxResult, TransactionDetails};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::{AccountId, Fee, TxResponse};
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/tauritxresult.ts"))]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct TauriTxResult {
|
||||
block_height: u64,
|
||||
code: u32,
|
||||
details: TransactionDetails,
|
||||
gas_used: u64,
|
||||
gas_wanted: u64,
|
||||
tx_hash: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(export, export_to = "../src/types/rust/transactiondetails.ts")
|
||||
)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct TransactionDetails {
|
||||
amount: Coin,
|
||||
from_address: String,
|
||||
to_address: String,
|
||||
}
|
||||
|
||||
impl TauriTxResult {
|
||||
fn new(t: TxResponse, details: TransactionDetails) -> TauriTxResult {
|
||||
TauriTxResult {
|
||||
block_height: t.height.value(),
|
||||
code: t.tx_result.code.value(),
|
||||
details,
|
||||
gas_used: t.tx_result.gas_used.value(),
|
||||
gas_wanted: t.tx_result.gas_wanted.value(),
|
||||
tx_hash: t.hash.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
use validator_client::nymd::{AccountId, Fee};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn send(
|
||||
address: &str,
|
||||
amount: Coin,
|
||||
amount: DecCoin,
|
||||
memo: String,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriTxResult, BackendError> {
|
||||
let address = AccountId::from_str(address)?;
|
||||
let amount = amount.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
let result = nymd_client!(state)
|
||||
.send(&address, vec![amount.clone()], memo, fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<SendTxResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let amount_base = guard.attempt_convert_to_base_coin(amount.clone())?;
|
||||
|
||||
let to_address = AccountId::from_str(address)?;
|
||||
let from_address = guard.current_client()?.nymd.address().to_string();
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Send: display_amount = {}, base_amount = {}, from = {}, to = {}, fee = {:?}",
|
||||
amount,
|
||||
amount_base,
|
||||
from_address,
|
||||
to_address,
|
||||
fee,
|
||||
);
|
||||
let raw_res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.send(&to_address, vec![amount_base], memo, fee)
|
||||
.await?;
|
||||
Ok(TauriTxResult::new(
|
||||
result,
|
||||
TransactionDetails {
|
||||
from_address: nymd_client!(state).address().to_string(),
|
||||
to_address: address.to_string(),
|
||||
amount: amount.into(),
|
||||
},
|
||||
))
|
||||
log::info!("<<< tx hash = {}", raw_res.hash.to_string());
|
||||
let res = SendTxResult::new(
|
||||
raw_res,
|
||||
TransactionDetails::new(amount, from_address, to_address.to_string()),
|
||||
fee_amount,
|
||||
);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -2,17 +2,15 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::mixnet::admin::TauriContractStateParams;
|
||||
use crate::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::State;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::WalletState;
|
||||
use mixnet_contract_common::{ContractStateParams, ExecuteMsg};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use nym_wallet_types::admin::TauriContractStateParams;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_update_contract_settings(
|
||||
params: TauriContractStateParams,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let mixnet_contract_settings_params: ContractStateParams = params.try_into()?;
|
||||
@@ -28,5 +26,5 @@ pub async fn simulate_update_contract_settings(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::state::State;
|
||||
use crate::state::WalletState;
|
||||
use nym_types::currency::DecCoin;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::{AccountId, MsgSend};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_send(
|
||||
address: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
amount: DecCoin,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let amount_base = guard.attempt_convert_to_base_coin(amount.clone())?;
|
||||
|
||||
let to_address = AccountId::from_str(address)?;
|
||||
let amount = amount.into_backend_coin(guard.current_network().denom())?;
|
||||
let amount = vec![amount_base.into()];
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let from_address = client.nymd.address().clone();
|
||||
@@ -29,9 +28,9 @@ pub async fn simulate_send(
|
||||
let msg = MsgSend {
|
||||
from_address,
|
||||
to_address,
|
||||
amount: vec![amount.into()],
|
||||
amount,
|
||||
};
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::State;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::WalletState;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::{ExecuteMsg, Gateway, MixNode};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use nym_types::currency::DecCoin;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
pledge: DecCoin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge = pledge.into_backend_coin(guard.current_network().denom())?;
|
||||
let pledge = guard.attempt_convert_to_base_coin(pledge)?;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
@@ -36,12 +35,12 @@ pub async fn simulate_bond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -56,18 +55,18 @@ pub async fn simulate_unbond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
pledge: DecCoin,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge = pledge.into_backend_coin(guard.current_network().denom())?;
|
||||
let pledge = guard.attempt_convert_to_base_coin(pledge)?;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
@@ -83,12 +82,12 @@ pub async fn simulate_bond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -103,13 +102,13 @@ pub async fn simulate_unbond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_update_mixnode(
|
||||
profit_margin_percent: u8,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -126,17 +125,17 @@ pub async fn simulate_update_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
amount: DecCoin,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let delegation = amount.into_backend_coin(guard.current_network().denom())?;
|
||||
let delegation = guard.attempt_convert_to_base_coin(amount)?;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let mixnet_contract = client.nymd.mixnet_contract_address();
|
||||
@@ -151,13 +150,13 @@ pub async fn simulate_delegate_to_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -174,7 +173,63 @@ pub async fn simulate_undelegate_from_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_claim_operator_reward(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client.nymd.simulate_claim_operator_reward(None).await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_compound_operator_reward(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client.nymd.simulate_compound_operator_reward(None).await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client
|
||||
.nymd
|
||||
.simulate_claim_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client
|
||||
.nymd
|
||||
.simulate_compound_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::coin::Coin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use nym_types::fees::FeeDetails;
|
||||
use validator_client::nymd::cosmwasm_client::types::GasInfo;
|
||||
use validator_client::nymd::{tx, CosmosCoin, Fee, GasPrice};
|
||||
|
||||
@@ -28,29 +27,13 @@ impl SimulateResult {
|
||||
gas_price,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FeeDetails {
|
||||
// expected to be used by the wallet in order to display detailed fee information to the user
|
||||
pub amount: Option<Coin>,
|
||||
pub fee: Fee,
|
||||
}
|
||||
|
||||
impl SimulateResult {
|
||||
pub fn detailed_fee(&self) -> FeeDetails {
|
||||
FeeDetails {
|
||||
amount: self.to_fee_amount().map(Into::into),
|
||||
fee: self.to_fee(),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_fee_amount(&self) -> Option<CosmosCoin> {
|
||||
pub(crate) fn to_fee_amount(&self) -> Option<CosmosCoin> {
|
||||
self.gas_info
|
||||
.map(|gas_info| &self.gas_price * gas_info.gas_used)
|
||||
}
|
||||
|
||||
fn to_fee(&self) -> Fee {
|
||||
pub(crate) fn to_fee(&self) -> Fee {
|
||||
self.to_fee_amount()
|
||||
.and_then(|fee_amount| {
|
||||
self.gas_info.map(|gas_info| {
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::State;
|
||||
use crate::operations::simulate::{FeeDetails, SimulateResult};
|
||||
use crate::WalletState;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::IdentityKey;
|
||||
use mixnet_contract_common::{Gateway, MixNode};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use nym_types::currency::DecCoin;
|
||||
use vesting_contract_common::ExecuteMsg;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
pledge: DecCoin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge = pledge.into_backend_coin(guard.current_network().denom())?;
|
||||
let pledge = guard.attempt_convert_to_base_coin(pledge)?;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
@@ -37,12 +36,12 @@ pub async fn simulate_vesting_bond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -57,18 +56,18 @@ pub async fn simulate_vesting_unbond_gateway(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
pledge: DecCoin,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge = pledge.into_backend_coin(guard.current_network().denom())?;
|
||||
let pledge = guard.attempt_convert_to_base_coin(pledge)?;
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
@@ -85,12 +84,12 @@ pub async fn simulate_vesting_bond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -105,13 +104,13 @@ pub async fn simulate_vesting_unbond_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_update_mixnode(
|
||||
profit_margin_percent: u8,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
|
||||
@@ -128,16 +127,16 @@ pub async fn simulate_vesting_update_mixnode(
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_withdraw_vested_coins(
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
amount: DecCoin,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let amount = amount.into_backend_coin(guard.current_network().denom())?;
|
||||
let amount = guard.attempt_convert_to_base_coin(amount)?.into();
|
||||
|
||||
let client = guard.current_client()?;
|
||||
let vesting_contract = client.nymd.vesting_contract_address();
|
||||
@@ -145,14 +144,74 @@ pub async fn simulate_withdraw_vested_coins(
|
||||
|
||||
let msg = client.nymd.wrap_contract_execute_message(
|
||||
vesting_contract,
|
||||
&ExecuteMsg::WithdrawVestedCoins {
|
||||
amount: amount.into(),
|
||||
},
|
||||
&ExecuteMsg::WithdrawVestedCoins { amount },
|
||||
vec![],
|
||||
)?;
|
||||
|
||||
let result = client.nymd.simulate(vec![msg]).await?;
|
||||
Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee())
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_claim_operator_reward(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client
|
||||
.nymd
|
||||
.simulate_vesting_claim_operator_reward(None)
|
||||
.await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_compound_operator_reward(
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client
|
||||
.nymd
|
||||
.simulate_vesting_compound_operator_reward(None)
|
||||
.await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_claim_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client
|
||||
.nymd
|
||||
.simulate_vesting_claim_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_compound_delegator_reward(
|
||||
mix_identity: IdentityKey,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.current_client()?;
|
||||
|
||||
let result = client
|
||||
.nymd
|
||||
.simulate_vesting_compound_delegator_reward(mix_identity, None)
|
||||
.await?;
|
||||
let gas_price = client.nymd.gas_price().clone();
|
||||
guard.create_detailed_fee(SimulateResult::new(result.gas_info, gas_price))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
|
||||
use crate::api_client;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use crate::state::WalletState;
|
||||
use validator_client::models::{
|
||||
CoreNodeStatusResponse, InclusionProbabilityResponse, MixnodeStatusResponse,
|
||||
RewardEstimationResponse, StakeSaturationResponse,
|
||||
@@ -15,7 +13,7 @@ use validator_client::models::{
|
||||
pub async fn mixnode_core_node_status(
|
||||
identity: &str,
|
||||
since: Option<i64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<CoreNodeStatusResponse, BackendError> {
|
||||
Ok(api_client!(state)
|
||||
.get_mixnode_core_status_count(identity, since)
|
||||
@@ -26,7 +24,7 @@ pub async fn mixnode_core_node_status(
|
||||
pub async fn gateway_core_node_status(
|
||||
identity: &str,
|
||||
since: Option<i64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<CoreNodeStatusResponse, BackendError> {
|
||||
Ok(api_client!(state)
|
||||
.get_gateway_core_status_count(identity, since)
|
||||
@@ -36,7 +34,7 @@ pub async fn gateway_core_node_status(
|
||||
#[tauri::command]
|
||||
pub async fn mixnode_status(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<MixnodeStatusResponse, BackendError> {
|
||||
Ok(api_client!(state).get_mixnode_status(identity).await?)
|
||||
}
|
||||
@@ -44,7 +42,7 @@ pub async fn mixnode_status(
|
||||
#[tauri::command]
|
||||
pub async fn mixnode_reward_estimation(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<RewardEstimationResponse, BackendError> {
|
||||
Ok(api_client!(state)
|
||||
.get_mixnode_reward_estimation(identity)
|
||||
@@ -54,7 +52,7 @@ pub async fn mixnode_reward_estimation(
|
||||
#[tauri::command]
|
||||
pub async fn mixnode_stake_saturation(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<StakeSaturationResponse, BackendError> {
|
||||
Ok(api_client!(state)
|
||||
.get_mixnode_stake_saturation(identity)
|
||||
@@ -64,7 +62,7 @@ pub async fn mixnode_stake_saturation(
|
||||
#[tauri::command]
|
||||
pub async fn mixnode_inclusion_probability(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<InclusionProbabilityResponse, BackendError> {
|
||||
Ok(api_client!(state)
|
||||
.get_mixnode_inclusion_probability(identity)
|
||||
|
||||
@@ -1,81 +1,165 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::state::WalletState;
|
||||
use crate::{Gateway, MixNode};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::transaction::TransactionExecuteResult;
|
||||
use validator_client::nymd::{Fee, VestingSigningClient};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
pledge: DecCoin,
|
||||
owner_signature: String,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
let pledge = pledge.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.vesting_bond_gateway(gateway, &owner_signature, pledge, fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Bond gateway with locked tokens: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}",
|
||||
gateway.identity_key,
|
||||
pledge,
|
||||
pledge_base,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.vesting_bond_gateway(gateway, &owner_signature, pledge_base, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_gateway(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state).vesting_unbond_gateway(fee).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_mixnode(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state).vesting_unbond_mixnode(fee).await?;
|
||||
Ok(())
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Unbond gateway bonded with locked tokens, fee = {:?}",
|
||||
fee
|
||||
);
|
||||
let res = nymd_client!(state).vesting_unbond_gateway(fee).await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
pledge: DecCoin,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
let pledge = pledge.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.vesting_bond_mixnode(mixnode, &owner_signature, pledge, fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let pledge_base = guard.attempt_convert_to_base_coin(pledge.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Bond mixnode with locked tokens: identity_key = {}, pledge_display = {}, pledge_base = {}, fee = {:?}",
|
||||
mixnode.identity_key,
|
||||
pledge,
|
||||
pledge_base,
|
||||
fee
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.vesting_bond_mixnode(mixnode, &owner_signature, pledge_base, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_mixnode(
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Unbond mixnode bonded with locked tokens, fee = {:?}",
|
||||
fee
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.vesting_unbond_mixnode(fee)
|
||||
.await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn withdraw_vested_coins(
|
||||
amount: Coin,
|
||||
amount: DecCoin,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
let amount = amount.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.withdraw_vested_coins(amount, fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let amount_base = guard.attempt_convert_to_base_coin(amount.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Withdraw vested liquid coins: amount_base = {}, amount_base = {}, fee = {:?}",
|
||||
amount,
|
||||
amount_base,
|
||||
fee
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.withdraw_vested_coins(amount_base, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_update_mixnode(
|
||||
profit_margin_percent: u8,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
nymd_client!(state)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Update mixnode bonded with locked tokens: profit_margin_percent = {}, fee = {:?}",
|
||||
profit_margin_percent,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.vesting_update_mixnode_config(profit_margin_percent, fee)
|
||||
.await?;
|
||||
Ok(())
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
@@ -1,62 +1,88 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::nymd_client;
|
||||
use crate::state::State;
|
||||
use crate::utils::DelegationEvent;
|
||||
use crate::utils::DelegationResult;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use crate::state::WalletState;
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::delegation::DelegationEvent;
|
||||
use nym_types::transaction::TransactionExecuteResult;
|
||||
use validator_client::nymd::{Fee, VestingSigningClient};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_pending_vesting_delegation_events(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<Vec<DelegationEvent>, BackendError> {
|
||||
log::info!(">>> Get pending delegations from vesting contract");
|
||||
|
||||
let guard = state.read().await;
|
||||
let reg = guard.registered_coins()?;
|
||||
let client = &guard.current_client()?.nymd;
|
||||
let vesting_contract = client.vesting_contract_address();
|
||||
|
||||
Ok(client
|
||||
let events = client
|
||||
.get_pending_delegation_events(
|
||||
client.address().to_string(),
|
||||
Some(vesting_contract.to_string()),
|
||||
)
|
||||
.await?
|
||||
.await?;
|
||||
|
||||
log::info!("<<< {} events", events.len());
|
||||
log::trace!("<<< {:?}", events);
|
||||
|
||||
Ok(events
|
||||
.into_iter()
|
||||
.map(|delegation_event| delegation_event.into())
|
||||
.collect::<Vec<DelegationEvent>>())
|
||||
.map(|event| DelegationEvent::from_mixnet_contract(event, reg))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
amount: DecCoin,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
let delegation = amount.into_backend_coin(state.read().await.current_network().denom())?;
|
||||
nymd_client!(state)
|
||||
.vesting_delegate_to_mixnode(identity, delegation.clone(), fee)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let delegation = guard.attempt_convert_to_base_coin(amount.clone())?;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
|
||||
log::info!(
|
||||
">>> Delegate to mixnode with locked tokens: identity_key = {}, amount_display = {}, amount_base = {}, fee = {:?}",
|
||||
identity,
|
||||
amount,
|
||||
delegation,
|
||||
fee
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.vesting_delegate_to_mixnode(identity, delegation, fee)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
nymd_client!(state).address().as_ref(),
|
||||
identity,
|
||||
Some(delegation.into()),
|
||||
))
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
nymd_client!(state)
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Undelegate from mixnode delegated with locked tokens: identity_key = {}, fee = {:?}",
|
||||
identity,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nymd
|
||||
.vesting_undelegate_from_mixnode(identity, fee)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
nymd_client!(state).address().as_ref(),
|
||||
identity,
|
||||
None,
|
||||
))
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
@@ -1,103 +1,4 @@
|
||||
use crate::coin::Coin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vesting_contract::vesting::Account as VestingAccount;
|
||||
use vesting_contract::vesting::VestingPeriod as VestingVestingPeriod;
|
||||
use vesting_contract_common::OriginalVestingResponse as VestingOriginalVestingResponse;
|
||||
use vesting_contract_common::PledgeData as VestingPledgeData;
|
||||
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod queries;
|
||||
pub mod rewards;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/pledgedata.ts"))]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct PledgeData {
|
||||
pub amount: Coin,
|
||||
pub block_time: u64,
|
||||
}
|
||||
|
||||
impl From<VestingPledgeData> for PledgeData {
|
||||
fn from(data: VestingPledgeData) -> Self {
|
||||
Self {
|
||||
amount: data.amount().into(),
|
||||
block_time: data.block_time().seconds(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PledgeData {
|
||||
fn and_then(data: VestingPledgeData) -> Option<Self> {
|
||||
Some(data.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(export, export_to = "../src/types/rust/originalvestingresponse.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct OriginalVestingResponse {
|
||||
amount: Coin,
|
||||
number_of_periods: usize,
|
||||
period_duration: u64,
|
||||
}
|
||||
|
||||
impl From<VestingOriginalVestingResponse> for OriginalVestingResponse {
|
||||
fn from(data: VestingOriginalVestingResponse) -> Self {
|
||||
Self {
|
||||
amount: data.amount().into(),
|
||||
number_of_periods: data.number_of_periods(),
|
||||
period_duration: data.period_duration(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
test,
|
||||
ts(export, export_to = "../src/types/rust/vestingaccountinfo.ts")
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct VestingAccountInfo {
|
||||
owner_address: String,
|
||||
staking_address: Option<String>,
|
||||
start_time: u64,
|
||||
periods: Vec<VestingPeriod>,
|
||||
coin: Coin,
|
||||
}
|
||||
|
||||
impl From<VestingAccount> for VestingAccountInfo {
|
||||
fn from(account: VestingAccount) -> Self {
|
||||
let mut periods = Vec::new();
|
||||
for period in account.periods() {
|
||||
periods.push(period.into());
|
||||
}
|
||||
Self {
|
||||
owner_address: account.owner_address().to_string(),
|
||||
staking_address: account.staking_address().map(|a| a.to_string()),
|
||||
start_time: account.start_time().seconds(),
|
||||
periods,
|
||||
coin: account.coin().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[cfg_attr(test, ts(export, export_to = "../src/types/rust/vestingperiod.ts"))]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct VestingPeriod {
|
||||
start_time: u64,
|
||||
period_seconds: u64,
|
||||
}
|
||||
|
||||
impl From<VestingVestingPeriod> for VestingPeriod {
|
||||
fn from(period: VestingVestingPeriod) -> Self {
|
||||
Self {
|
||||
start_time: period.start_time,
|
||||
period_seconds: period.period_seconds,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user