Feature/wallet bonding fixes (#5064)
* bonding and unbonding for nym nodes
This commit is contained in:
Generated
+34
-34
@@ -173,7 +173,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -658,7 +658,7 @@ dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1022,7 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1083,7 +1083,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1751,7 +1751,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1931,7 +1931,7 @@ dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3667,7 +3667,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3854,7 +3854,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3983,7 +3983,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4140,7 +4140,7 @@ dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4151,9 +4151,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.79"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -4178,7 +4178,7 @@ dependencies = [
|
||||
"itertools 0.11.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4704,7 +4704,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4798,9 +4798,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.214"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -4825,13 +4825,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.214"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4842,14 +4842,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.128"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||
dependencies = [
|
||||
"itoa 1.0.9",
|
||||
"memchr",
|
||||
@@ -4865,7 +4865,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5219,7 +5219,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5262,9 +5262,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.55"
|
||||
version = "2.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
|
||||
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5769,7 +5769,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5856,7 +5856,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6021,7 +6021,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6097,7 +6097,7 @@ checksum = "0ea0b99e8ec44abd6f94a18f28f7934437809dd062820797c52401298116f70e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
@@ -6201,7 +6201,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6316,7 +6316,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -6350,7 +6350,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -6979,7 +6979,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.55",
|
||||
"syn 2.0.85",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -116,12 +116,12 @@ pub async fn generate_gateway_bonding_msg_payload(
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn generate_nym_node_bonding_msg_payload(
|
||||
nym_node: NymNode,
|
||||
nymnode: NymNode,
|
||||
cost_params: NodeCostParams,
|
||||
pledge: DecCoin,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<String, BackendError> {
|
||||
nym_node_bonding_msg_payload(nym_node, cost_params, pledge, state).await
|
||||
nym_node_bonding_msg_payload(nymnode, cost_params, pledge, state).await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -2,15 +2,15 @@ import React, { createContext, useContext, useMemo, useState } from 'react';
|
||||
import { CurrencyDenom } from '@nymproject/types';
|
||||
import { TBondNymNodeArgs, TBondMixNodeArgs } from 'src/types';
|
||||
|
||||
const defaultNymNodeValues: TBondNymNodeArgs['nymNode'] = {
|
||||
const defaultNymNodeValues: TBondNymNodeArgs['nymnode'] = {
|
||||
identity_key: 'H6rXWgsW89QsVyaNSS3qBe9zZFLhBS6Gn3YRkGFSoFW9',
|
||||
custom_http_port: 1,
|
||||
custom_http_port: null,
|
||||
host: '1.1.1.1',
|
||||
};
|
||||
|
||||
const defaultCostParams = (denom: CurrencyDenom): TBondNymNodeArgs['costParams'] => ({
|
||||
interval_operating_cost: { amount: '40', denom },
|
||||
profit_margin_percent: '10',
|
||||
profit_margin_percent: '40',
|
||||
});
|
||||
|
||||
const defaultAmount = (denom: CurrencyDenom): TBondMixNodeArgs['pledge'] => ({
|
||||
@@ -21,14 +21,14 @@ const defaultAmount = (denom: CurrencyDenom): TBondMixNodeArgs['pledge'] => ({
|
||||
interface FormContextType {
|
||||
step: 1 | 2 | 3 | 4;
|
||||
setStep: React.Dispatch<React.SetStateAction<1 | 2 | 3 | 4>>;
|
||||
nymNodeData: TBondNymNodeArgs['nymNode'];
|
||||
setNymNodeData: React.Dispatch<React.SetStateAction<TBondNymNodeArgs['nymNode']>>;
|
||||
nymNodeData: TBondNymNodeArgs['nymnode'];
|
||||
setNymNodeData: React.Dispatch<React.SetStateAction<TBondNymNodeArgs['nymnode']>>;
|
||||
costParams: TBondNymNodeArgs['costParams'];
|
||||
setCostParams: React.Dispatch<React.SetStateAction<TBondNymNodeArgs['costParams']>>;
|
||||
amountData: TBondMixNodeArgs['pledge'];
|
||||
setAmountData: React.Dispatch<React.SetStateAction<TBondMixNodeArgs['pledge']>>;
|
||||
signature?: string;
|
||||
setSignature: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
signature: string;
|
||||
setSignature: React.Dispatch<React.SetStateAction<string>>;
|
||||
onError: (e: string) => void;
|
||||
}
|
||||
|
||||
@@ -41,9 +41,8 @@ const FormContext = createContext<FormContextType>({
|
||||
setCostParams: () => {},
|
||||
amountData: defaultAmount('nym'),
|
||||
setAmountData: () => {},
|
||||
signature: undefined,
|
||||
signature: '',
|
||||
setSignature: () => {},
|
||||
|
||||
onError: () => {},
|
||||
});
|
||||
|
||||
@@ -52,10 +51,10 @@ const FormContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const denom = 'nym';
|
||||
|
||||
const [step, setStep] = useState<1 | 2 | 3 | 4>(1);
|
||||
const [nymNodeData, setNymNodeData] = useState<TBondNymNodeArgs['nymNode']>(defaultNymNodeValues);
|
||||
const [nymNodeData, setNymNodeData] = useState<TBondNymNodeArgs['nymnode']>(defaultNymNodeValues);
|
||||
const [costParams, setCostParams] = useState<TBondNymNodeArgs['costParams']>(defaultCostParams(denom));
|
||||
const [amountData, setAmountData] = useState<TBondNymNodeArgs['pledge']>(defaultAmount(denom));
|
||||
const [signature, setSignature] = useState<string>();
|
||||
const [signature, setSignature] = useState('');
|
||||
|
||||
const onError = (e: string) => {
|
||||
console.error(e);
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Stack, TextField, Box, FormHelperText } from '@mui/material';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { TBondNymNodeArgs } from 'src/types';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { SimpleModal } from 'src/components/Modals/SimpleModal';
|
||||
import { CurrencyFormField } from '@nymproject/react/currency/CurrencyFormField';
|
||||
import { checkHasEnoughFunds } from 'src/utils';
|
||||
import { nymNodeAmountSchema } from './amountValidationSchema';
|
||||
|
||||
const defaultNymNodeCostParamValues: TBondNymNodeArgs['costParams'] = {
|
||||
profit_margin_percent: '10',
|
||||
interval_operating_cost: { amount: '40', denom: 'nym' },
|
||||
};
|
||||
|
||||
const defaultNymNodePledgeValue: TBondNymNodeArgs['pledge'] = {
|
||||
amount: '100',
|
||||
denom: 'nym',
|
||||
};
|
||||
import { useFormContext } from './FormContext';
|
||||
|
||||
type NymNodeDataProps = {
|
||||
onClose: () => void;
|
||||
@@ -26,6 +16,7 @@ type NymNodeDataProps = {
|
||||
};
|
||||
|
||||
const NymNodeAmount = ({ onClose, onBack, onNext, step }: NymNodeDataProps) => {
|
||||
const { setAmountData, setCostParams, amountData, costParams } = useFormContext();
|
||||
const {
|
||||
formState: { errors },
|
||||
register,
|
||||
@@ -36,21 +27,26 @@ const NymNodeAmount = ({ onClose, onBack, onNext, step }: NymNodeDataProps) => {
|
||||
} = useForm({
|
||||
mode: 'all',
|
||||
defaultValues: {
|
||||
pledge: defaultNymNodePledgeValue,
|
||||
...defaultNymNodeCostParamValues,
|
||||
pledge: amountData,
|
||||
...costParams,
|
||||
},
|
||||
resolver: yupResolver(nymNodeAmountSchema()),
|
||||
});
|
||||
|
||||
console.log(errors, 'errors');
|
||||
|
||||
const handleRequestValidation = async () => {
|
||||
const values = getValues();
|
||||
|
||||
const hasSufficientTokens = await checkHasEnoughFunds(values.pledge.amount);
|
||||
|
||||
if (hasSufficientTokens) {
|
||||
handleSubmit(onNext)();
|
||||
handleSubmit((args) => {
|
||||
setAmountData(args.pledge);
|
||||
setCostParams({
|
||||
profit_margin_percent: args.profit_margin_percent,
|
||||
interval_operating_cost: args.interval_operating_cost,
|
||||
});
|
||||
onNext();
|
||||
})();
|
||||
} else {
|
||||
setError('pledge.amount', { message: 'Not enough tokens' });
|
||||
}
|
||||
@@ -77,8 +73,8 @@ const NymNodeAmount = ({ onClose, onBack, onNext, step }: NymNodeDataProps) => {
|
||||
setValue('pledge.amount', newValue.amount, { shouldValidate: true });
|
||||
}}
|
||||
validationError={errors.pledge?.amount?.message}
|
||||
denom={defaultNymNodePledgeValue.denom}
|
||||
initialValue={defaultNymNodePledgeValue.amount}
|
||||
denom={amountData.denom}
|
||||
initialValue={amountData.amount}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
@@ -90,8 +86,8 @@ const NymNodeAmount = ({ onClose, onBack, onNext, step }: NymNodeDataProps) => {
|
||||
setValue('interval_operating_cost', newValue, { shouldValidate: true });
|
||||
}}
|
||||
validationError={errors.interval_operating_cost?.amount?.message}
|
||||
denom={defaultNymNodeCostParamValues.interval_operating_cost.denom}
|
||||
initialValue={defaultNymNodeCostParamValues.interval_operating_cost.amount}
|
||||
denom={costParams.interval_operating_cost.denom}
|
||||
initialValue={costParams.interval_operating_cost.amount}
|
||||
/>
|
||||
<FormHelperText>
|
||||
Monthly operational costs of running your node. If your node is in the active set the amount will be paid
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import React from 'react';
|
||||
import * as yup from 'yup';
|
||||
import { Stack, TextField, FormControlLabel, Checkbox } from '@mui/material';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { IdentityKeyFormField } from '@nymproject/react/mixnodes/IdentityKeyFormField';
|
||||
import { TBondNymNodeArgs } from 'src/types';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import * as yup from 'yup';
|
||||
import { isValidHostname, validateRawPort } from 'src/utils';
|
||||
import { SimpleModal } from 'src/components/Modals/SimpleModal';
|
||||
|
||||
const defaultNymNodeValues: TBondNymNodeArgs['nymNode'] = {
|
||||
identity_key: 'H6rXWgsW89QsVyaNSS3qBe9zZFLhBS6Gn3YRkGFSoFW9',
|
||||
custom_http_port: 1,
|
||||
host: '1.1.1.1',
|
||||
};
|
||||
import { useFormContext } from './FormContext';
|
||||
|
||||
const yupValidationSchema = yup.object().shape({
|
||||
identity_key: yup.string().required('Identity key is required'),
|
||||
@@ -24,8 +18,13 @@ const yupValidationSchema = yup.object().shape({
|
||||
|
||||
custom_http_port: yup
|
||||
.number()
|
||||
.required('A custom http port is required')
|
||||
.test('valid-http', 'A valid http port is required', (value) => (value ? validateRawPort(value) : false)),
|
||||
.nullable()
|
||||
.test('valid-http', 'A valid http port is required', (value) => {
|
||||
if (value === null) {
|
||||
return true;
|
||||
}
|
||||
return value ? validateRawPort(value) : false;
|
||||
}),
|
||||
});
|
||||
|
||||
type NymNodeDataProps = {
|
||||
@@ -36,6 +35,7 @@ type NymNodeDataProps = {
|
||||
};
|
||||
|
||||
const NymNodeData = ({ onClose, onNext, step }: NymNodeDataProps) => {
|
||||
const { setNymNodeData, nymNodeData } = useFormContext();
|
||||
const {
|
||||
formState: { errors },
|
||||
register,
|
||||
@@ -43,14 +43,17 @@ const NymNodeData = ({ onClose, onNext, step }: NymNodeDataProps) => {
|
||||
handleSubmit,
|
||||
} = useForm({
|
||||
mode: 'all',
|
||||
defaultValues: defaultNymNodeValues,
|
||||
defaultValues: nymNodeData,
|
||||
resolver: yupResolver(yupValidationSchema),
|
||||
});
|
||||
|
||||
const [showAdvancedOptions, setShowAdvancedOptions] = React.useState(false);
|
||||
|
||||
const handleNext = async () => {
|
||||
handleSubmit(onNext)();
|
||||
handleSubmit((args) => {
|
||||
setNymNodeData(args);
|
||||
onNext();
|
||||
})();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -69,7 +72,7 @@ const NymNodeData = ({ onClose, onNext, step }: NymNodeDataProps) => {
|
||||
required
|
||||
fullWidth
|
||||
label="Identity Key"
|
||||
initialValue={defaultNymNodeValues.identity_key}
|
||||
initialValue={nymNodeData.identity_key}
|
||||
errorText={errors.identity_key?.message?.toString()}
|
||||
onChanged={(value) => setValue('identity_key', value, { shouldValidate: true })}
|
||||
showTickOnValid={false}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import * as yup from 'yup';
|
||||
import { Stack, TextField, Typography } from '@mui/material';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { CopyToClipboard } from 'src/components/CopyToClipboard';
|
||||
@@ -7,9 +8,11 @@ import { SimpleModal } from 'src/components/Modals/SimpleModal';
|
||||
import { useBondingContext } from 'src/context';
|
||||
import { TBondNymNodeArgs } from 'src/types';
|
||||
import { Signature } from 'src/pages/bonding/types';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { useFormContext } from './FormContext';
|
||||
|
||||
const NymNodeSignature = ({
|
||||
nymNode,
|
||||
nymnode,
|
||||
pledge,
|
||||
costParams,
|
||||
step,
|
||||
@@ -17,27 +20,38 @@ const NymNodeSignature = ({
|
||||
onClose,
|
||||
onBack,
|
||||
}: {
|
||||
nymNode: TBondNymNodeArgs['nymNode'];
|
||||
nymnode: TBondNymNodeArgs['nymnode'];
|
||||
pledge: TBondNymNodeArgs['pledge'];
|
||||
costParams: TBondNymNodeArgs['costParams'];
|
||||
step: number;
|
||||
onNext: (data: Signature) => void;
|
||||
onNext: () => void;
|
||||
onClose: () => void;
|
||||
onBack: () => void;
|
||||
}) => {
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [error, setError] = useState<string>();
|
||||
const { generateNymNodeMsgPayload } = useBondingContext();
|
||||
const { signature, setSignature } = useFormContext();
|
||||
|
||||
const yupValidationSchema = yup.object().shape({
|
||||
signature: yup.string().required('Signature is required'),
|
||||
});
|
||||
|
||||
const {
|
||||
register,
|
||||
formState: { errors },
|
||||
} = useForm<Signature>();
|
||||
handleSubmit,
|
||||
} = useForm<Signature>({
|
||||
defaultValues: {
|
||||
signature,
|
||||
},
|
||||
resolver: yupResolver(yupValidationSchema),
|
||||
});
|
||||
|
||||
const generateMessage = async () => {
|
||||
try {
|
||||
const msg = await generateNymNodeMsgPayload({
|
||||
nymNode,
|
||||
nymnode,
|
||||
pledge,
|
||||
costParams,
|
||||
});
|
||||
@@ -53,10 +67,10 @@ const NymNodeSignature = ({
|
||||
|
||||
useEffect(() => {
|
||||
generateMessage();
|
||||
}, [nymNode, pledge, costParams]);
|
||||
}, []);
|
||||
|
||||
const onSubmit = async (data: Signature) => {
|
||||
onNext(data);
|
||||
const handleNext = async () => {
|
||||
handleSubmit(onNext)();
|
||||
};
|
||||
|
||||
if (error) {
|
||||
@@ -66,11 +80,7 @@ const NymNodeSignature = ({
|
||||
return (
|
||||
<SimpleModal
|
||||
open
|
||||
onOk={() =>
|
||||
onSubmit({
|
||||
signature: 'signature',
|
||||
})
|
||||
}
|
||||
onOk={handleNext}
|
||||
onClose={onClose}
|
||||
header="Bond Nym Node"
|
||||
subHeader={`Step ${step}/3`}
|
||||
@@ -95,10 +105,13 @@ const NymNodeSignature = ({
|
||||
</Stack>
|
||||
<TextField
|
||||
{...register('signature')}
|
||||
onChange={(e) => setSignature(e.target.value)}
|
||||
id="outlined-multiline-static"
|
||||
name="signature"
|
||||
rows={3}
|
||||
placeholder="Paste Signature"
|
||||
helperText={errors.signature?.message}
|
||||
error={Boolean(errors.signature)}
|
||||
multiline
|
||||
fullWidth
|
||||
required
|
||||
|
||||
@@ -5,8 +5,8 @@ import { isLessThan, isGreaterThan, validateAmount } from 'src/utils';
|
||||
const operatingCostAndPmValidation = (params?: TauriContractStateParams) => {
|
||||
const defaultParams = {
|
||||
profit_margin_percent: {
|
||||
minimum: parseFloat(params?.profit_margin.minimum || '0%'),
|
||||
maximum: parseFloat(params?.profit_margin.maximum || '100%'),
|
||||
minimum: parseFloat(params?.profit_margin.minimum || '20%'),
|
||||
maximum: parseFloat(params?.profit_margin.maximum || '50%'),
|
||||
},
|
||||
|
||||
interval_operating_cost: {
|
||||
|
||||
@@ -2,18 +2,24 @@ import React, { useContext, useEffect } from 'react';
|
||||
import { ConfirmTx } from 'src/components/ConfirmTX';
|
||||
import { ModalListItem } from 'src/components/Modals/ModalListItem';
|
||||
import { useGetFee } from 'src/hooks/useGetFee';
|
||||
import { Signature } from 'src/pages/bonding/types';
|
||||
import { BalanceWarning } from 'src/components/FeeWarning';
|
||||
import { AppContext } from 'src/context';
|
||||
import { TBondNymNodeArgs } from 'src/types';
|
||||
import FormContextProvider, { useFormContext } from '../forms/nym-node/FormContext';
|
||||
import NymNodeData from '../forms/nym-node/NymNodeData';
|
||||
import NymNodeAmount from '../forms/nym-node/NymNodeAmount';
|
||||
import NymNodeSignature from '../forms/nym-node/NymNodeSignature';
|
||||
|
||||
export const BondNymNodeModal = ({ onClose }: { onClose: () => void }) => {
|
||||
export const BondNymNodeModal = ({
|
||||
onClose,
|
||||
onBond,
|
||||
}: {
|
||||
onClose: () => void;
|
||||
onBond: (data: TBondNymNodeArgs) => Promise<void>;
|
||||
}) => {
|
||||
const { fee, resetFeeState, feeError } = useGetFee();
|
||||
const { userBalance } = useContext(AppContext);
|
||||
const { setStep, step, onError, setSignature, amountData, costParams, nymNodeData } = useFormContext();
|
||||
const { setStep, step, onError, signature, amountData, costParams, nymNodeData } = useFormContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (feeError) {
|
||||
@@ -21,12 +27,17 @@ export const BondNymNodeModal = ({ onClose }: { onClose: () => void }) => {
|
||||
}
|
||||
}, [feeError]);
|
||||
|
||||
const handleUpdateMixnodeData = async () => {
|
||||
const handleUpdateNymnodeData = async () => {
|
||||
setStep(2);
|
||||
};
|
||||
|
||||
const handleUpdateSignature = async (data: Signature) => {
|
||||
setSignature(data.signature);
|
||||
const handleBond = async () => {
|
||||
onBond({
|
||||
nymnode: nymNodeData,
|
||||
pledge: amountData,
|
||||
costParams,
|
||||
msgSignature: signature,
|
||||
});
|
||||
};
|
||||
|
||||
const handleConfirm = async () => {};
|
||||
@@ -51,7 +62,7 @@ export const BondNymNodeModal = ({ onClose }: { onClose: () => void }) => {
|
||||
}
|
||||
|
||||
if (step === 1) {
|
||||
return <NymNodeData onClose={onClose} onBack={onClose} onNext={handleUpdateMixnodeData} step={step} />;
|
||||
return <NymNodeData onClose={onClose} onBack={onClose} onNext={handleUpdateNymnodeData} step={step} />;
|
||||
}
|
||||
|
||||
if (step === 2) {
|
||||
@@ -61,10 +72,10 @@ export const BondNymNodeModal = ({ onClose }: { onClose: () => void }) => {
|
||||
if (step === 3) {
|
||||
return (
|
||||
<NymNodeSignature
|
||||
nymNode={nymNodeData}
|
||||
nymnode={nymNodeData}
|
||||
pledge={amountData}
|
||||
costParams={costParams}
|
||||
onNext={handleUpdateSignature}
|
||||
onNext={handleBond}
|
||||
onClose={onClose}
|
||||
onBack={() => setStep(2)}
|
||||
step={step}
|
||||
@@ -75,14 +86,22 @@ export const BondNymNodeModal = ({ onClose }: { onClose: () => void }) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export const BondNymNodeModalWithState = ({ open, onClose }: { open: boolean; onClose: () => void }) => {
|
||||
export const BondNymNode = ({
|
||||
open,
|
||||
onClose,
|
||||
onBond,
|
||||
}: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onBond: (data: TBondNymNodeArgs) => Promise<void>;
|
||||
}) => {
|
||||
if (!open) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<FormContextProvider>
|
||||
<BondNymNodeModal onClose={onClose} />
|
||||
<BondNymNodeModal onClose={onClose} onBond={onBond} />
|
||||
</FormContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { Typography } from '@mui/material';
|
||||
import { TBondedNode } from 'src/context';
|
||||
import { useGetFee } from 'src/hooks/useGetFee';
|
||||
import { isGateway, isMixnode } from 'src/types';
|
||||
import { TBondedGateway } from 'src/requests/gatewayDetails';
|
||||
import { TBondedMixnode } from 'src/requests/mixnodeDetails';
|
||||
import { ModalFee } from '../../Modals/ModalFee';
|
||||
import { ModalListItem } from '../../Modals/ModalListItem';
|
||||
import { SimpleModal } from '../../Modals/SimpleModal';
|
||||
@@ -16,7 +15,7 @@ import {
|
||||
} from '../../../requests';
|
||||
|
||||
interface Props {
|
||||
node: TBondedMixnode | TBondedGateway;
|
||||
node: TBondedNode;
|
||||
onConfirm: () => Promise<void>;
|
||||
onClose: () => void;
|
||||
onError: (e: string) => void;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { FeeDetails, TransactionExecuteResult } from '@nymproject/types';
|
||||
import { isGateway, isMixnode, TUpdateBondArgs, isNymNode, TNymNodeSignatureArgs } from 'src/types';
|
||||
import { isGateway, isMixnode, TUpdateBondArgs, isNymNode, TNymNodeSignatureArgs, TBondNymNodeArgs } from 'src/types';
|
||||
import { Console } from 'src/utils/console';
|
||||
import useGetNodeDetails from 'src/hooks/useGetNodeDetails';
|
||||
import { TBondedNymNode } from 'src/requests/nymNodeDetails';
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
migrateVestedMixnode as tauriMigrateVestedMixnode,
|
||||
migrateLegacyMixnode as migrateLegacyMixnodeReq,
|
||||
migrateLegacyGateway as migrateLegacyGatewayReq,
|
||||
bondNymNode,
|
||||
} from '../requests';
|
||||
|
||||
export type TBondedNode = TBondedMixnode | TBondedGateway | TBondedNymNode;
|
||||
@@ -31,6 +32,7 @@ export type TBondingContext = {
|
||||
isVestingAccount: boolean;
|
||||
refresh: () => void;
|
||||
unbond: (fee?: FeeDetails) => Promise<TransactionExecuteResult | undefined>;
|
||||
bond: (args: TBondNymNodeArgs) => Promise<TransactionExecuteResult | undefined>;
|
||||
updateBondAmount: (data: TUpdateBondArgs) => Promise<TransactionExecuteResult | undefined>;
|
||||
redeemRewards: (fee?: FeeDetails) => Promise<TransactionExecuteResult | undefined>;
|
||||
generateNymNodeMsgPayload: (data: TNymNodeSignatureArgs) => Promise<string | undefined>;
|
||||
@@ -41,6 +43,9 @@ export type TBondingContext = {
|
||||
export const BondingContext = createContext<TBondingContext>({
|
||||
isLoading: true,
|
||||
refresh: async () => undefined,
|
||||
bond: async () => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
unbond: async () => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
@@ -70,7 +75,11 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
|
||||
|
||||
const { userBalance, clientDetails, network } = useContext(AppContext);
|
||||
|
||||
const { bondedNode, isLoading: isBondedNodeLoading } = useGetNodeDetails(clientDetails?.client_address, network);
|
||||
const {
|
||||
bondedNode,
|
||||
isLoading: isBondedNodeLoading,
|
||||
getNodeDetails,
|
||||
} = useGetNodeDetails(clientDetails?.client_address, network);
|
||||
|
||||
useEffect(() => {
|
||||
userBalance.fetchBalance();
|
||||
@@ -91,6 +100,30 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
|
||||
resetState();
|
||||
};
|
||||
|
||||
const bond = async (data: TBondNymNodeArgs) => {
|
||||
let tx;
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
tx = await bondNymNode({
|
||||
...data,
|
||||
costParams: {
|
||||
...data.costParams,
|
||||
profit_margin_percent: toPercentFloatString(data.costParams.profit_margin_percent),
|
||||
},
|
||||
});
|
||||
if (clientDetails?.client_address) {
|
||||
await getNodeDetails(clientDetails?.client_address);
|
||||
}
|
||||
} catch (e) {
|
||||
Console.warn(e);
|
||||
setError(`an error occurred: ${e as string}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
return tx;
|
||||
};
|
||||
|
||||
const unbond = async (fee?: FeeDetails) => {
|
||||
let tx;
|
||||
setIsLoading(true);
|
||||
@@ -143,7 +176,7 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
|
||||
|
||||
try {
|
||||
const message = await generateNymNodeMsgPayloadReq({
|
||||
nymNode: data.nymNode,
|
||||
nymnode: data.nymnode,
|
||||
pledge: data.pledge,
|
||||
costParams: {
|
||||
...data.costParams,
|
||||
@@ -187,6 +220,7 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
|
||||
isLoading: isLoading || isBondedNodeLoading,
|
||||
error,
|
||||
bondedNode,
|
||||
bond,
|
||||
unbond,
|
||||
refresh,
|
||||
redeemRewards,
|
||||
|
||||
@@ -133,6 +133,14 @@ export const MockBondingContextProvider = ({
|
||||
return TxResultMock;
|
||||
};
|
||||
|
||||
const bond = async (): Promise<TransactionExecuteResult> => {
|
||||
setIsLoading(true);
|
||||
await mockSleep(SLEEP_MS);
|
||||
setBondedData(bondedMixnodeMock);
|
||||
setIsLoading(false);
|
||||
return TxResultMock;
|
||||
};
|
||||
|
||||
const unbond = async (): Promise<TransactionExecuteResult> => {
|
||||
setIsLoading(true);
|
||||
await mockSleep(SLEEP_MS);
|
||||
@@ -189,6 +197,7 @@ export const MockBondingContextProvider = ({
|
||||
error,
|
||||
bondMixnode,
|
||||
bondGateway,
|
||||
bond,
|
||||
unbond,
|
||||
refresh,
|
||||
redeemRewards,
|
||||
|
||||
@@ -63,6 +63,7 @@ const useGetNodeDetails = (clientAddress?: string, network?: string) => {
|
||||
bondedNode,
|
||||
isLoading,
|
||||
isError,
|
||||
getNodeDetails,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ import { ConfirmationDetailProps, ConfirmationDetailsModal } from 'src/component
|
||||
import { ErrorModal } from 'src/components/Modals/ErrorModal';
|
||||
import { LoadingModal } from 'src/components/Modals/LoadingModal';
|
||||
import { AppContext, urls } from 'src/context/main';
|
||||
import { isGateway, isMixnode, isNymNode, TUpdateBondArgs } from 'src/types';
|
||||
import { isGateway, isMixnode, isNymNode, TBondNymNodeArgs, TUpdateBondArgs } from 'src/types';
|
||||
import { BondedGateway } from 'src/components/Bonding/BondedGateway';
|
||||
import { RedeemRewardsModal } from 'src/components/Bonding/modals/RedeemRewardsModal';
|
||||
import { VestingWarningModal } from 'src/components/VestingWarningModal';
|
||||
import MigrateLegacyNode from 'src/components/Bonding/modals/MigrateLegacyNode';
|
||||
import { BondedNymNode } from 'src/components/Bonding/BondedNymNode';
|
||||
import { UpdateBondAmountNymNode } from 'src/components/Bonding/modals/UpdateBondAmountNymNode';
|
||||
import { BondNymNodeModalWithState } from 'src/components/Bonding/modals/BondNymNodeModal';
|
||||
import { BondNymNode } from 'src/components/Bonding/modals/BondNymNodeModal';
|
||||
import { BondingContextProvider, useBondingContext } from '../../context';
|
||||
|
||||
export const Bonding = () => {
|
||||
@@ -44,6 +44,7 @@ export const Bonding = () => {
|
||||
redeemRewards,
|
||||
updateBondAmount,
|
||||
refresh,
|
||||
bond,
|
||||
migrateVestedMixnode,
|
||||
migrateLegacyNode,
|
||||
} = useBondingContext();
|
||||
@@ -74,6 +75,18 @@ export const Bonding = () => {
|
||||
setShowMigrateLegacyNodeModal(shouldShowMigrateLegacyNodeModal());
|
||||
}, [bondedNode]);
|
||||
|
||||
const handleBondNymNode = async (data: TBondNymNodeArgs) => {
|
||||
setShowModal(undefined);
|
||||
const tx = await bond(data);
|
||||
if (tx) {
|
||||
setConfirmationDetails({
|
||||
status: 'success',
|
||||
title: 'Bonding successful',
|
||||
txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleMigrateVestedMixnode = async () => {
|
||||
setShowMigrationModal(false);
|
||||
const tx = await migrateVestedMixnode();
|
||||
@@ -250,7 +263,7 @@ export const Bonding = () => {
|
||||
/>
|
||||
)}
|
||||
|
||||
<BondNymNodeModalWithState open={showModal === 'bond-nymnode'} onClose={handleCloseModal} />
|
||||
<BondNymNode open={showModal === 'bond-nymnode'} onClose={handleCloseModal} onBond={handleBondNymNode} />
|
||||
|
||||
{showModal === 'update-bond-oversaturated' && uncappedSaturation && (
|
||||
<BondOversaturatedModal
|
||||
|
||||
@@ -7,7 +7,6 @@ import { isMixnode, isNymNode } from 'src/types';
|
||||
|
||||
interface Props {
|
||||
bondedNode: TBondedNode;
|
||||
|
||||
onConfirm: () => Promise<void>;
|
||||
onError: (e: string) => void;
|
||||
}
|
||||
@@ -71,7 +70,7 @@ export const NodeUnbondPage = ({ bondedNode, onConfirm, onError }: Props) => {
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{isConfirmed && !isNymNode(bondedNode) && (
|
||||
{isConfirmed && (
|
||||
<UnbondModal
|
||||
node={bondedNode}
|
||||
onConfirm={async () => {
|
||||
|
||||
@@ -36,7 +36,7 @@ export type TBondNymNodeArgs = TNymNodeSignatureArgs & {
|
||||
};
|
||||
|
||||
export type TNymNodeSignatureArgs = {
|
||||
nymNode: NymNode;
|
||||
nymnode: NymNode;
|
||||
costParams: NodeCostParams;
|
||||
pledge: DecCoin;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user