Gateway settings (#2725)

* add gateway settings button

* remove unneeded mixnode type check

* add additional properties to gateway type

* update node settings nav options

* set up gateway update requests

* create gateway settings page

* use update gateway validation

* PR updates

* dont show playground on gateways

* set up gateway config update

* fix lint errors in wallet

* run cargo fmt
This commit is contained in:
Fouad
2023-03-23 09:38:33 +00:00
committed by GitHub
parent 28e6e9140c
commit a7610a7a88
40 changed files with 408 additions and 34 deletions
+3
View File
@@ -119,6 +119,7 @@ fn main() {
vesting::bond::vesting_unbond_mixnode,
vesting::bond::vesting_update_mixnode_cost_params,
vesting::bond::vesting_update_mixnode_config,
vesting::bond::vesting_update_gateway_config,
vesting::bond::withdraw_vested_coins,
vesting::delegate::vesting_delegate_to_mixnode,
vesting::delegate::vesting_undelegate_from_mixnode,
@@ -154,6 +155,7 @@ fn main() {
simulate::mixnet::simulate_unbond_mixnode,
simulate::mixnet::simulate_update_mixnode_config,
simulate::mixnet::simulate_update_mixnode_cost_params,
simulate::mixnet::simulate_update_gateway_config,
simulate::mixnet::simulate_delegate_to_mixnode,
simulate::mixnet::simulate_undelegate_from_mixnode,
simulate::vesting::simulate_vesting_delegate_to_mixnode,
@@ -164,6 +166,7 @@ fn main() {
simulate::vesting::simulate_vesting_pledge_more,
simulate::vesting::simulate_vesting_unbond_mixnode,
simulate::vesting::simulate_vesting_update_mixnode_config,
simulate::vesting::simulate_vesting_update_gateway_config,
simulate::vesting::simulate_vesting_update_mixnode_cost_params,
simulate::vesting::simulate_withdraw_vested_coins,
simulate::vesting::simulate_vesting_claim_delegator_reward,
@@ -5,8 +5,8 @@ use crate::error::BackendError;
use crate::operations::simulate::FeeDetails;
use crate::WalletState;
use nym_contracts_common::signing::MessageSignature;
use nym_mixnet_contract_common::MixNodeConfigUpdate;
use nym_mixnet_contract_common::{ExecuteMsg, Gateway, MixId, MixNode};
use nym_mixnet_contract_common::{GatewayConfigUpdate, MixNodeConfigUpdate};
use nym_types::currency::DecCoin;
use nym_types::mixnode::MixNodeCostParams;
@@ -130,6 +130,19 @@ pub async fn simulate_update_mixnode_config(
.await
}
#[tauri::command]
pub async fn simulate_update_gateway_config(
update: GatewayConfigUpdate,
state: tauri::State<'_, WalletState>,
) -> Result<FeeDetails, BackendError> {
simulate_mixnet_operation(
ExecuteMsg::UpdateGatewayConfig { new_config: update },
None,
&state,
)
.await
}
#[tauri::command]
pub async fn simulate_delegate_to_mixnode(
mix_id: MixId,
@@ -5,8 +5,8 @@ use crate::error::BackendError;
use crate::operations::simulate::FeeDetails;
use crate::WalletState;
use nym_contracts_common::signing::MessageSignature;
use nym_mixnet_contract_common::MixNodeConfigUpdate;
use nym_mixnet_contract_common::{Gateway, MixId, MixNode};
use nym_mixnet_contract_common::{GatewayConfigUpdate, MixNodeConfigUpdate};
use nym_types::currency::DecCoin;
use nym_types::mixnode::MixNodeCostParams;
use nym_vesting_contract_common::ExecuteMsg;
@@ -142,6 +142,19 @@ pub async fn simulate_vesting_update_mixnode_config(
.await
}
#[tauri::command]
pub async fn simulate_vesting_update_gateway_config(
update: GatewayConfigUpdate,
state: tauri::State<'_, WalletState>,
) -> Result<FeeDetails, BackendError> {
simulate_vesting_operation(
ExecuteMsg::UpdateGatewayConfig { new_config: update },
None,
&state,
)
.await
}
#[tauri::command]
pub async fn simulate_vesting_delegate_to_mixnode(
mix_id: MixId,
@@ -3,7 +3,7 @@ use crate::nyxd_client;
use crate::state::WalletState;
use crate::{Gateway, MixNode};
use nym_contracts_common::signing::MessageSignature;
use nym_mixnet_contract_common::MixNodeConfigUpdate;
use nym_mixnet_contract_common::{GatewayConfigUpdate, MixNodeConfigUpdate};
use crate::operations::helpers::{
verify_gateway_bonding_sign_payload, verify_mixnode_bonding_sign_payload,
@@ -254,3 +254,28 @@ pub async fn vesting_update_mixnode_config(
res, fee_amount,
)?)
}
#[tauri::command]
pub async fn vesting_update_gateway_config(
update: GatewayConfigUpdate,
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!(
">>> Update gateway config with locked tokens: update = {}, fee = {:?}",
update.to_inline_json(),
fee,
);
let res = guard
.current_client()?
.nyxd
.vesting_update_gateway_config(update, fee)
.await?;
log::info!("<<< tx hash = {}", res.transaction_hash);
log::trace!("<<< {:?}", res);
Ok(TransactionExecuteResult::from_execute_result(
res, fee_amount,
)?)
}
@@ -1,10 +1,12 @@
import React from 'react';
import { Stack, Typography } from '@mui/material';
import { Box, Button, Stack, Typography } from '@mui/material';
import { Link } from '@nymproject/react/link/Link';
import { TBondedGateway, urls } from 'src/context';
import { NymCard } from 'src/components';
import { Network } from 'src/types';
import { IdentityKey } from 'src/components/IdentityKey';
import { useNavigate } from 'react-router-dom';
import { Node as NodeIcon } from '../../svg-icons/node';
import { Cell, Header, NodeTable } from './NodeTable';
import { BondedGatewayActions, TBondedGatwayActions } from './BondedGatewayAction';
@@ -43,6 +45,7 @@ export const BondedGateway = ({
onActionSelect: (action: TBondedGatwayActions) => void;
}) => {
const { name, bond, ip, identityKey, routingScore } = gateway;
const navigate = useNavigate();
const cells: Cell[] = [
{
cell: `${bond.amount} ${bond.denom}`,
@@ -86,6 +89,18 @@ export const BondedGateway = ({
<IdentityKey identityKey={identityKey} />
</Stack>
}
Action={
<Box>
<Button
variant="text"
color="secondary"
onClick={() => navigate('/bonding/node-settings')}
startIcon={<NodeIcon />}
>
Gateway Settings
</Button>
</Box>
}
>
<NodeTable headers={headers} cells={cells} />
{network && (
@@ -66,3 +66,17 @@ export const amountSchema = Yup.object().shape({
}),
}),
});
export const updateGatewayValidationSchema = Yup.object().shape({
host: Yup.string()
.required('A host is required')
.test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)),
mixPort: Yup.number()
.required('A mixport is required')
.test('valid-mixport', 'A valid mixport is required', (value) => (value ? validateRawPort(value) : false)),
httpApiPort: Yup.number()
.required('A clients port is required')
.test('valid-clients', 'A valid clients port is required', (value) => (value ? validateRawPort(value) : false)),
});
+13 -9
View File
@@ -10,6 +10,7 @@ import {
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import Big from 'big.js';
import {
EnumNodeType,
isGateway,
isMixnode,
TBondGatewayArgs,
@@ -93,7 +94,7 @@ export interface TBondedGateway {
identityKey: string;
ip: string;
bond: DecCoin;
location?: string; // TODO not yet available, only available in Network Explorer API
location?: string;
proxy?: string;
host: string;
httpApiPort: number;
@@ -104,7 +105,6 @@ export interface TBondedGateway {
current: number;
average: number;
};
isUnbonding: boolean;
}
export type TokenPool = 'locked' | 'balance';
@@ -267,7 +267,7 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
const refresh = useCallback(async () => {
setIsLoading(true);
if (ownership.hasOwnership && clientDetails) {
if (ownership.hasOwnership && ownership.nodeType === EnumNodeType.mixnode && clientDetails) {
try {
const data = await getMixnodeBondDetails();
let operatorRewards;
@@ -330,21 +330,25 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
}
}
if (ownership.hasOwnership) {
if (ownership.hasOwnership && ownership.nodeType === EnumNodeType.gateway) {
try {
const data = await getGatewayBondDetails();
if (data) {
const { gateway, proxy } = data;
const nodeDescription = await getNodeDescription(data.gateway.host, data.gateway.clients_port);
const routingScore = await getGatewayReportDetails(data.gateway.identity_key);
setBondedNode({
name: nodeDescription?.name,
identityKey: data.gateway.identity_key,
ip: data.gateway.host,
location: data.gateway.location,
identityKey: gateway.identity_key,
mixPort: gateway.mix_port,
httpApiPort: gateway.clients_port,
host: gateway.host,
ip: gateway.host,
location: gateway.location,
bond: decCoinToDisplay(data.pledge_amount),
proxy: data.proxy,
proxy,
routingScore,
isUnbonding: false,
version: gateway.version,
} as TBondedGateway);
}
} catch (e: any) {
-1
View File
@@ -47,7 +47,6 @@ const bondedGatewayMock: TBondedGateway = {
average: 100,
current: 100,
},
isUnbonding: false,
};
const TxResultMock: TransactionExecuteResult = {
@@ -17,7 +17,7 @@ import { isMixnode } from 'src/types';
import { getIntervalAsDate } from 'src/utils';
import { NodeGeneralSettings } from './settings-pages/general-settings';
import { NodeUnbondPage } from './settings-pages/NodeUnbondPage';
import { createNavItems } from './node-settings.constant';
import { makeNavItems } from './node-settings.constant';
import { ApyPlayground } from './apy-playground';
export const NodeSettings = () => {
@@ -87,7 +87,7 @@ export const NodeSettings = () => {
</Box>
<Box sx={{ width: '100%' }}>
<Tabs
tabs={createNavItems(isMixnode(bondedNode))}
tabs={makeNavItems(isMixnode(bondedNode))}
selectedTab={value}
onChange={handleChange}
tabSx={{
@@ -1,5 +1,7 @@
export const createNavItems = (isMixnode: boolean) => {
const navItems = ['Unbond'];
if (isMixnode) return ['General', 'Playground', ...navItems];
export const makeNavItems = (isMixnode: boolean) => {
const navItems = ['General', 'Unbond'];
if (isMixnode) navItems.splice(1, 0, 'Playground');
return navItems;
};
@@ -0,0 +1,203 @@
import React, { useState } from 'react';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { Button, Divider, Typography, TextField, Grid, Box } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import {
simulateUpdateGatewayConfig,
simulateVestingUpdateGatewayConfig,
updateGatewayConfig,
vestingUpdateGatewayConfig,
} from 'src/requests';
import { TBondedGateway, useBondingContext } from 'src/context/bonding';
import { SimpleModal } from 'src/components/Modals/SimpleModal';
import { Console } from 'src/utils/console';
import { Alert } from 'src/components/Alert';
import { ConfirmTx } from 'src/components/ConfirmTX';
import { useGetFee } from 'src/hooks/useGetFee';
import { LoadingModal } from 'src/components/Modals/LoadingModal';
import { updateGatewayValidationSchema } from 'src/components/Bonding/forms/gatewayValidationSchema';
export const GeneralGatewaySettings = ({ bondedNode }: { bondedNode: TBondedGateway }) => {
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
const { getFee, fee, resetFeeState } = useGetFee();
const { refresh } = useBondingContext();
const theme = useTheme();
const {
register,
handleSubmit,
formState: { errors, isSubmitting, isDirty, isValid },
} = useForm({
resolver: yupResolver(updateGatewayValidationSchema),
mode: 'onChange',
defaultValues: {
host: bondedNode.host,
mixPort: bondedNode.mixPort,
httpApiPort: bondedNode.httpApiPort,
},
});
const onSubmit = async (data: any) => {
resetFeeState();
const { host, mixPort, httpApiPort } = data;
try {
const GatewayConfigParams = {
host,
mix_port: mixPort,
clients_port: httpApiPort,
location: bondedNode.location!,
version: bondedNode.version,
verloc_port: bondedNode.verlocPort,
};
if (bondedNode.proxy) {
await vestingUpdateGatewayConfig(GatewayConfigParams, fee?.fee);
} else {
await updateGatewayConfig(GatewayConfigParams, fee?.fee);
}
setOpenConfirmationModal(true);
} catch (error) {
Console.error(error);
}
};
return (
<Grid container xs item>
{fee && (
<ConfirmTx
open
header="Update node settings"
fee={fee}
onConfirm={handleSubmit((d) => onSubmit(d))}
onPrev={resetFeeState}
onClose={resetFeeState}
/>
)}
{isSubmitting && <LoadingModal />}
<Alert
title={
<Box sx={{ fontWeight: 600 }}>
Changing these values will ONLY change the data about your node on the blockchain. Remember to change your
nodes config file with the same values too
</Box>
}
dismissable
/>
<Grid container>
<Grid item container direction="row" alignItems="left" justifyContent="space-between" padding={3}>
<Grid item>
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1 }}>
Port
</Typography>
</Grid>
<Grid spacing={3} item container alignItems="center" xs={12} md={6}>
<Grid item width={1}>
<TextField
{...register('mixPort')}
name="mixPort"
label="Mix Port"
fullWidth
error={!!errors.mixPort}
helperText={errors.mixPort?.message}
InputLabelProps={{ shrink: true }}
/>
</Grid>
<Grid item width={1}>
<TextField
{...register('httpApiPort')}
name="httpApiPort"
label="Client WS API Port"
fullWidth
error={!!errors.httpApiPort}
helperText={errors.httpApiPort?.message}
InputLabelProps={{ shrink: true }}
/>
</Grid>
</Grid>
</Grid>
<Grid item container direction="row" alignItems="left" justifyContent="space-between" padding={3}>
<Grid item>
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1 }}>
Host
</Typography>
</Grid>
<Grid spacing={3} item container alignItems="center" xs={12} md={6}>
<Grid item width={1}>
<TextField
{...register('host')}
name="host"
label="Host"
fullWidth
error={!!errors.host}
helperText={errors.host?.message}
InputLabelProps={{ shrink: true }}
/>
</Grid>
</Grid>
</Grid>
<Divider flexItem />
<Grid container justifyContent="end">
<Button
size="large"
variant="contained"
disabled={isSubmitting || !isDirty || !isValid}
onClick={handleSubmit((data) =>
getFee(bondedNode.proxy ? simulateVestingUpdateGatewayConfig : simulateUpdateGatewayConfig, {
host: data.host,
mix_port: data.mixPort,
clients_port: data.httpApiPort,
location: bondedNode.location!,
version: bondedNode.version,
verloc_port: bondedNode.verlocPort,
}),
)}
sx={{ m: 3 }}
>
Submit changes to the blockchain
</Button>
</Grid>
</Grid>
<SimpleModal
open={openConfirmationModal}
header="Your changes are submitted to the blockchain"
subHeader="Remember to change the values
on your gatewayss config file too."
okLabel="close"
hideCloseIcon
displayInfoIcon
onOk={async () => {
setOpenConfirmationModal(false);
await refresh();
}}
buttonFullWidth
sx={{
width: '450px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}}
headerStyles={{
width: '100%',
mb: 1,
textAlign: 'center',
color: theme.palette.nym.nymWallet.text.blue,
fontSize: 16,
}}
subHeaderStyles={{
width: '100%',
mb: 1,
textAlign: 'center',
color: 'main',
fontSize: 14,
}}
/>
</Grid>
);
};
@@ -15,7 +15,7 @@ import { ConfirmTx } from 'src/components/ConfirmTX';
import { useGetFee } from 'src/hooks/useGetFee';
import { LoadingModal } from 'src/components/Modals/LoadingModal';
export const InfoSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
export const GeneralMixnodeSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
const { getFee, fee, resetFeeState } = useGetFee();
@@ -141,7 +141,7 @@ export const InfoSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBon
<TextField
{...register('host')}
name="host"
label="host"
label="Host"
fullWidth
error={!!errors.host}
helperText={errors.host?.message}
@@ -1,25 +1,50 @@
import React, { useState } from 'react';
import { Box, Button, Divider, Grid } from '@mui/material';
import { isMixnode } from 'src/types';
import { TBondedMixnode, TBondedGateway } from '../../../../../context/bonding';
import { InfoSettings } from './InfoSettings';
import { isGateway, isMixnode } from 'src/types';
import { TBondedMixnode, TBondedGateway } from 'src/context/bonding';
import { GeneralMixnodeSettings } from './GeneralMixnodeSettings';
import { ParametersSettings } from './ParametersSettings';
import { GeneralGatewaySettings } from './GeneralGatewaySettings';
const nodeGeneralNav = ['Node info', 'Parameters'];
const makeGeneralNav = (bondedNode: TBondedMixnode | TBondedGateway) => {
const navItems = ['Info'];
if (isMixnode(bondedNode)) {
navItems.push('Parameters');
}
return navItems;
};
export const NodeGeneralSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
const [settingsCard, setSettingsCard] = useState<string>(nodeGeneralNav[0]);
// TODO: Check what happens with a gateway
const [navSelection, setNavSelection] = useState<number>(0);
const getSettings = () => {
switch (navSelection) {
case 0: {
if (isMixnode(bondedNode)) return <GeneralMixnodeSettings bondedNode={bondedNode} />;
if (isGateway(bondedNode)) return <GeneralGatewaySettings bondedNode={bondedNode} />;
break;
}
case 1: {
if (isMixnode(bondedNode)) return <ParametersSettings bondedNode={bondedNode} />;
break;
}
default:
return null;
}
return undefined;
};
return (
<Box sx={{ pl: 3, pt: 3 }}>
<Grid container direction="row" spacing={3}>
<Grid item container direction="column" xs={3}>
{nodeGeneralNav.map((item) => (
{makeGeneralNav(bondedNode).map((item, index) => (
<Button
size="small"
sx={{
fontSize: 14,
color: settingsCard === item ? 'primary.main' : 'inherit',
color: navSelection === index ? 'primary.main' : 'inherit',
justifyContent: 'start',
':hover': {
bgcolor: 'transparent',
@@ -27,15 +52,14 @@ export const NodeGeneralSettings = ({ bondedNode }: { bondedNode: TBondedMixnode
},
}}
key={item}
onClick={() => setSettingsCard(item)}
onClick={() => setNavSelection(index)}
>
{item}
</Button>
))}
</Grid>
<Divider orientation="vertical" flexItem />
{settingsCard === nodeGeneralNav[0] && <InfoSettings bondedNode={bondedNode} />}
{settingsCard === nodeGeneralNav[1] && isMixnode(bondedNode) && <ParametersSettings bondedNode={bondedNode} />}
{getSettings()}
</Grid>
</Box>
);
+4
View File
@@ -5,6 +5,7 @@ import {
TransactionExecuteResult,
MixNodeConfigUpdate,
MixNodeCostParams,
GatewayConfigUpdate,
} from '@nymproject/types';
import {
EnumNodeType,
@@ -38,6 +39,9 @@ export const updateMixnodeCostParams = async (newCosts: MixNodeCostParams, fee?:
export const updateMixnodeConfig = async (update: MixNodeConfigUpdate, fee?: Fee) =>
invokeWrapper<TransactionExecuteResult>('update_mixnode_config', { update, fee });
export const updateGatewayConfig = async (update: GatewayConfigUpdate, fee?: Fee) =>
invokeWrapper<TransactionExecuteResult>('update_gateway_config', { update, fee });
export const send = async (args: { amount: DecCoin; address: string; memo: string; fee?: Fee }) =>
invokeWrapper<SendTxResult>('send', args);
+14 -1
View File
@@ -1,4 +1,11 @@
import { FeeDetails, DecCoin, Gateway, MixNodeCostParams, MixNodeConfigUpdate } from '@nymproject/types';
import {
FeeDetails,
DecCoin,
Gateway,
MixNodeCostParams,
MixNodeConfigUpdate,
GatewayConfigUpdate,
} from '@nymproject/types';
import { TBondGatewayArgs, TBondMixNodeArgs } from 'src/types';
import { invokeWrapper } from './wrapper';
@@ -18,6 +25,9 @@ export const simulateUpdateMixnodeCostParams = async (newCosts: MixNodeCostParam
export const simulateUpdateMixnodeConfig = async (update: MixNodeConfigUpdate) =>
invokeWrapper<FeeDetails>('simulate_update_mixnode_config', { update });
export const simulateUpdateGatewayConfig = async (update: GatewayConfigUpdate) =>
invokeWrapper<FeeDetails>('simulate_update_gateway_config', { update });
export const simulateDelegateToMixnode = async (args: { mixId: number; amount: DecCoin }) =>
invokeWrapper<FeeDetails>('simulate_delegate_to_mixnode', args);
@@ -53,6 +63,9 @@ export const simulateVestingUpdateMixnodeCostParams = async (newCosts: MixNodeCo
export const simulateVestingUpdateMixnodeConfig = async (update: MixNodeConfigUpdate) =>
invokeWrapper<FeeDetails>('simulate_vesting_update_mixnode_config', { update });
export const simulateVestingUpdateGatewayConfig = async (update: GatewayConfigUpdate) =>
invokeWrapper<FeeDetails>('simulate_vesting_update_gateway_config', { update });
export const simulateWithdrawVestedCoins = async (args: any) =>
invokeWrapper<FeeDetails>('simulate_withdraw_vested_coins', args);
+4
View File
@@ -10,6 +10,7 @@ import {
VestingAccountInfo,
MixNodeCostParams,
MixNodeConfigUpdate,
GatewayConfigUpdate,
} from '@nymproject/types';
import { Fee } from '@nymproject/types/dist/types/rust/Fee';
import { invokeWrapper } from './wrapper';
@@ -80,6 +81,9 @@ export const vestingUpdateMixnodeCostParams = async (newCosts: MixNodeCostParams
export const vestingUpdateMixnodeConfig = async (update: MixNodeConfigUpdate, fee?: Fee) =>
invokeWrapper<TransactionExecuteResult>('vesting_update_mixnode_config', { update, fee });
export const vestingUpdateGatewayConfig = async (update: GatewayConfigUpdate, fee?: Fee) =>
invokeWrapper<TransactionExecuteResult>('vesting_update_gateway_config', { update, fee });
export const vestingDelegateToMixnode = async (mixId: number, amount: DecCoin, fee?: Fee) =>
invokeWrapper<TransactionExecuteResult>('vesting_delegate_to_mixnode', { mixId, amount, fee });
+2
View File
@@ -1 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type Network = 'QA' | 'SANDBOX' | 'MAINNET';
+2 -1
View File
@@ -1,4 +1,5 @@
import type { DecCoin } from '@nymproject/types';
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DecCoin } from '@nymproject/types/src/types/rust/DecCoin';
export interface TauriContractStateParams {
minimum_mixnode_pledge: DecCoin;
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface ValidatorUrl {
url: string;
name: string | null;
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ValidatorUrl } from './ValidatorUrl';
export interface ValidatorUrls {
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface GatewayCoreStatusResponse {
identity: string;
count: number;
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface Interval {
id: number;
epochs_in_interval: number;
@@ -1,6 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface IntervalRewardParams {
reward_pool: string;
staking_supply: string;
staking_supply_scale_factor: string;
epoch_reward_budget: string;
stake_saturation_point: string;
sybil_resistance: string;
@@ -1,6 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface IntervalRewardingParamsUpdate {
reward_pool: string | null;
staking_supply: string | null;
staking_supply_scale_factor: string | null;
sybil_resistance_percent: string | null;
active_set_work_factor: string | null;
interval_pool_emission: string | null;
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface MixNodeConfigUpdate {
host: string;
mix_port: number;
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DecCoin } from './DecCoin';
export interface MixNodeCostParams {
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { MixNodeBond } from './MixNodeBond';
import type { MixNodeRewarding } from './MixNodeRewarding';
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { MixNodeCostParams } from './MixNodeCostParams';
export interface MixNodeRewarding {
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface MixnodeCoreStatusResponse {
mix_id: number;
count: number;
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PendingEpochEventData } from './PendingEpochEventData';
export interface PendingEpochEvent {
@@ -1,7 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DecCoin } from './DecCoin';
export type PendingEpochEventData =
| { Delegate: { owner: string; mix_id: number; amount: DecCoin; proxy: string | null } }
| { Undelegate: { owner: string; mix_id: number; proxy: string | null } }
| { PledgeMore: { mix_id: number; amount: DecCoin } }
| { UnbondMixnode: { mix_id: number } }
| { UpdateActiveSetSize: { new_size: number } };
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PendingIntervalEventData } from './PendingIntervalEventData';
export interface PendingIntervalEvent {
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { IntervalRewardingParamsUpdate } from './IntervalRewardingParamsUpdate';
import type { MixNodeCostParams } from './MixNodeCostParams';
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface RewardEstimate {
total_node_reward: string;
operator: string;
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Interval } from './Interval';
import type { RewardEstimate } from './RewardEstimate';
import type { RewardingParams } from './RewardingParams';
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { IntervalRewardParams } from './IntervalRewardParams';
export interface RewardingParams {
@@ -1 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SelectionChance = 'High' | 'Good' | 'Low';
@@ -1,3 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface UnbondedMixnode {
identity_key: string;
owner: string;
@@ -1,3 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DelegationEvent } from './DelegationEvent';
export interface WrappedDelegationEvent {
@@ -19,6 +19,7 @@ export * from './Gas';
export * from './GasInfo';
export * from './Gateway';
export * from './GatewayBond';
export * from './GatewayConfigUpdate';
export * from './GatewayCoreStatusResponse';
export * from './InclusionProbabilityResponse';
export * from './IntervalRewardingParamsUpdate';