adding a react context... imposible to avoid it at the end : (

This commit is contained in:
Gala
2023-10-05 19:11:10 +02:00
committed by Lorexia
parent f3dfbeb2b7
commit 4adf922b3f
5 changed files with 501 additions and 450 deletions
@@ -0,0 +1,171 @@
import * as React from 'react';
import { contracts } from '@nymproject/contract-clients';
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import { Coin, GasPrice } from '@cosmjs/stargate';
import { settings } from '../client';
const signerAccount = async (mnemonic: string) => {
// create a wallet to sign transactions with the mnemonic
const signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
prefix: 'n',
});
return signer;
};
const fetchSignerCosmosWasmClient = async (mnemonic: string) => {
const signer = await signerAccount(mnemonic);
// create a signing client we don't need to set the gas price conversion for queries
const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, {
gasPrice: GasPrice.fromString('0.025unym'),
});
return cosmWasmClient;
};
const fetchSignerClient = async (mnemonic) => {
const signer = await signerAccount(mnemonic);
// create a signing client we don't need to set the gas price conversion for queries
// if you want to connect without signer you'd write ".connect" and "url" as param
const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, {
gasPrice: GasPrice.fromString('0.025unym'),
});
/** create a mixnet contract client
* @param cosmWasmClient the client to use for signing and querying
* @param settings.address the bech32 address prefix (human readable part)
* @param settings.mixnetContractAddress the bech32 address prefix (human readable part)
* @returns the client in MixnetClient form
*/
const mixnetClient = new contracts.Mixnet.MixnetClient(
cosmWasmClient,
settings.address, // sender (that account of the signer)
settings.mixnetContractAddress, // contract address (different on mainnet, QA, etc)
);
return mixnetClient;
};
interface ApiState<RESPONSE> {
isLoading: boolean;
data?: RESPONSE;
error?: Error;
}
/**
* This context provides the state for wallet.
*/
interface WalletState {
cosmWasmSigner?: { getAccounts: () => void };
cosmWasmSignerClient?: { getBalance: (account: string, denom: string) => Coin };
nymWasmSignerClient?: ApiState<any>;
accountLoading: boolean;
account: string;
clientsAreLoading: boolean;
setConnectWithMnemonic?: (value: string) => void;
balance?: Coin;
balanceLoading: boolean;
}
export const WalletContext = React.createContext<WalletState>({
accountLoading: false,
account: '',
clientsAreLoading: false,
balanceLoading: false,
});
export const useWalletContext = (): React.ContextType<typeof WalletContext> =>
React.useContext<WalletState>(WalletContext);
export const WalletContextProvider = ({ children }: { children: JSX.Element }) => {
// wallet mnemonic
const [connectWithMnemonic, setConnectWithMnemonic] = React.useState<string>();
const [accountLoading, setAccountLoading] = React.useState<boolean>(false);
const [account, setAccount] = React.useState<string>();
const [clientsAreLoading, setClientsAreLoading] = React.useState<boolean>(false);
const [cosmWasmSignerClient, setCosmWasmSignerClient] = React.useState<any>();
const [nymWasmSignerClient, setNymWasmSignerClient] = React.useState<any>();
const [balance, setBalance] = React.useState<Coin>();
const [balanceLoading, setBalanceLoading] = React.useState<boolean>(false);
const getSignerAccount = async () => {
console.log('getSignerAccount');
setAccountLoading(true);
try {
const signer = await signerAccount(connectWithMnemonic);
const accounts = await signer.getAccounts();
if (accounts[0]) {
setAccount(accounts[0].address);
}
} catch (error) {
console.error(error);
}
setAccountLoading(false);
};
const getClients = async () => {
setClientsAreLoading(true);
try {
setCosmWasmSignerClient(await fetchSignerCosmosWasmClient(connectWithMnemonic));
setNymWasmSignerClient(await fetchSignerClient(connectWithMnemonic));
} catch (error) {
console.error(error);
}
setClientsAreLoading(false);
};
const getBalance = React.useCallback(async () => {
setBalanceLoading(true);
try {
const newBalance = await cosmWasmSignerClient?.getBalance(account, 'unym');
setBalance(newBalance);
} catch (error) {
console.error(error);
}
setBalanceLoading(false);
}, [account, cosmWasmSignerClient]);
React.useEffect(() => {
if (connectWithMnemonic) {
// when the mnemonic changes, remove all previous data
Promise.all([getSignerAccount(), getClients()]);
}
}, [connectWithMnemonic]);
React.useEffect(() => {
if (account && cosmWasmSignerClient) {
if (!balance) {
getBalance();
}
}
}, [account, cosmWasmSignerClient, balance, getBalance]);
const state = React.useMemo<WalletState>(
() => ({
accountLoading,
account,
clientsAreLoading,
cosmWasmSignerClient,
nymWasmSignerClient,
setConnectWithMnemonic,
balance,
balanceLoading,
}),
[
accountLoading,
account,
clientsAreLoading,
cosmWasmSignerClient,
nymWasmSignerClient,
setConnectWithMnemonic,
balance,
balanceLoading,
],
);
return <WalletContext.Provider value={state}>{children}</WalletContext.Provider>;
};
+24 -262
View File
@@ -1,283 +1,45 @@
import React, { useCallback, useEffect, useState } from 'react';
import { contracts } from '@nymproject/contract-clients';
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import { Coin, GasPrice } from '@cosmjs/stargate';
import React, { useCallback, useEffect, useState, createContext } from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { settings } from './client';
import { ConnectWallet } from './wallet/connect';
import { SendTokes } from './wallet/sendTokens';
import { Delegations } from './wallet/delegations';
import { WalletContextProvider } from './context/wallet';
const signerAccount = async (mnemonic) => {
// create a wallet to sign transactions with the mnemonic
const signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
prefix: 'n',
});
return signer;
};
const fetchSignerCosmosWasmClient = async (mnemonic: string) => {
const signer = await signerAccount(mnemonic);
// create a signing client we don't need to set the gas price conversion for queries
const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, {
gasPrice: GasPrice.fromString('0.025unym'),
});
return cosmWasmClient;
};
const fetchSignerClient = async (mnemonic) => {
const signer = await signerAccount(mnemonic);
// create a signing client we don't need to set the gas price conversion for queries
// if you want to connect without signer you'd write ".connect" and "url" as param
const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, {
gasPrice: GasPrice.fromString('0.025unym'),
});
/** create a mixnet contract client
* @param cosmWasmClient the client to use for signing and querying
* @param settings.address the bech32 address prefix (human readable part)
* @param settings.mixnetContractAddress the bech32 address prefix (human readable part)
* @returns the client in MixnetClient form
*/
const mixnetClient = new contracts.Mixnet.MixnetClient(
cosmWasmClient,
settings.address, // sender (that account of the signer)
settings.mixnetContractAddress, // contract address (different on mainnet, QA, etc)
);
return mixnetClient;
};
export const Wallet = ({ type }: { type: 'connect' | 'sendTokens' | 'delegations' }) => {
const [mnemonic, setMnemonic] = useState<string>();
const [signerCosmosWasmClient, setSignerCosmosWasmClient] = useState<any>();
const [signerClient, setSignerClient] = useState<any>();
const [account, setAccount] = useState<string>();
const [accountLoading, setAccountLoading] = useState<boolean>(false);
const [clientLoading, setClientLoading] = useState<boolean>(false);
const [balance, setBalance] = useState<Coin>();
const [balanceLoading, setBalanceLoading] = useState<boolean>(false);
const [log, setLog] = useState<React.ReactNode[]>([]);
const [sendingTokensLoader, setSendingTokensLoader] = useState<boolean>(false);
const [delegations, setDelegations] = useState<any>();
const [recipientAddress, setRecipientAddress] = useState<string>('');
const [delegationLoader, setDelegationLoader] = useState<boolean>(false);
const [undeledationLoader, setUndeledationLoader] = useState<boolean>(false);
const [withdrawLoading, setWithdrawLoading] = useState<boolean>(false);
const [connectButtonText, setConnectButtonText] = useState<string>('Connect');
const getBalance = useCallback(async () => {
setBalanceLoading(true);
try {
const newBalance = await signerCosmosWasmClient?.getBalance(account, 'unym');
setBalance(newBalance);
} catch (error) {
console.error(error);
}
setBalanceLoading(false);
}, [account, signerCosmosWasmClient]);
const getSignerAccount = async () => {
setAccountLoading(true);
try {
const signer = await signerAccount(mnemonic);
const accounts = await signer.getAccounts();
if (accounts[0]) {
setAccount(accounts[0].address);
}
} catch (error) {
console.error(error);
}
setAccountLoading(false);
};
const getClients = async () => {
setClientLoading(true);
try {
setSignerCosmosWasmClient(await fetchSignerCosmosWasmClient(mnemonic));
setSignerClient(await fetchSignerClient(mnemonic));
} catch (error) {
console.error(error);
}
setClientLoading(false);
};
const getDelegations = useCallback(async () => {
const newDelegations = await signerClient.getDelegatorDelegations({
delegator: settings.address,
});
setDelegations(newDelegations);
}, [signerClient]);
const connect = () => {
getSignerAccount();
getClients();
};
// Start Undelgate All
const doUndelegateAll = async () => {
if (!signerClient) {
return;
}
setUndeledationLoader(true);
try {
// eslint-disable-next-line no-restricted-syntax
for (const delegation of delegations.delegations) {
// eslint-disable-next-line no-await-in-loop
await signerClient.undelegateFromMixnode({ mixId: delegation.mix_id }, 'auto');
}
} catch (error) {
console.error(error);
}
setUndeledationLoader(false);
};
// End Undelgate All
// Start Delegate
const doDelegate = async ({ mixId, amount }: { mixId: number; amount: number }) => {
if (!signerClient) {
return;
}
setDelegationLoader(true);
try {
const res = await signerClient.delegateToMixnode({ mixId }, 'auto', undefined, [
{ amount: `${amount}`, denom: 'unym' },
]);
console.log('res', res);
setLog((prev) => [
...prev,
<div key={JSON.stringify(res, null, 2)}>
<code style={{ marginRight: '2rem' }}>{new Date().toLocaleTimeString()}</code>
<pre>{JSON.stringify(res, null, 2)}</pre>
</div>,
]);
} catch (error) {
console.error(error);
}
setDelegationLoader(false);
};
// End delegate
// Sending tokens
const doSendTokens = async (amount: string) => {
const memo = 'test sending tokens';
setSendingTokensLoader(true);
try {
const res = await signerCosmosWasmClient.sendTokens(
account,
recipientAddress,
[{ amount, denom: 'unym' }],
'auto',
memo,
);
setLog((prev) => [
...prev,
<div key={JSON.stringify(res, null, 2)}>
<code style={{ marginRight: '2rem' }}>{new Date().toLocaleTimeString()}</code>
<pre>{JSON.stringify(res, null, 2)}</pre>
</div>,
]);
} catch (error) {
console.error(error);
}
setSendingTokensLoader(false);
};
// End send tokens
// Start Withdraw Rewards
const doWithdrawRewards = async () => {
const delegatorAddress = '';
const validatorAdress = '';
const memo = 'test sending tokens';
setWithdrawLoading(true);
try {
const res = await signerCosmosWasmClient.withdrawRewards(delegatorAddress, validatorAdress, 'auto', memo);
setLog((prev) => [
...prev,
<div key={JSON.stringify(res, null, 2)}>
<code style={{ marginRight: '2rem' }}>{new Date().toLocaleTimeString()}</code>
<pre>{JSON.stringify(res, null, 2)}</pre>
</div>,
]);
} catch (error) {
console.error(error);
}
setWithdrawLoading(false);
};
// End Withdraw Rewards
useEffect(() => {
if (account && signerCosmosWasmClient) {
if (!balance) {
setBalanceLoading(true);
getBalance();
setBalanceLoading(false);
}
}
}, [account, signerCosmosWasmClient, balance, getBalance]);
useEffect(() => {
if (signerClient && !delegations) {
console.log('getDelegations');
getDelegations();
}
}, [signerClient, getDelegations, delegations]);
useEffect(() => {
if (accountLoading || clientLoading || balanceLoading) {
setConnectButtonText('Loading...');
} else if (balance) {
setConnectButtonText('Connected');
}
setConnectButtonText('Connect');
}, [accountLoading, clientLoading, balanceLoading]);
return (
<Box padding={3}>
{type === 'connect' && (
<ConnectWallet
setMnemonic={setMnemonic}
connect={connect}
mnemonic={mnemonic}
accountLoading={accountLoading}
clientLoading={clientLoading}
balanceLoading={balanceLoading}
account={account}
balance={balance}
connectButtonText={connectButtonText}
/>
)}
{type === 'sendTokens' && (
<SendTokes
setRecipientAddress={setRecipientAddress}
doSendTokens={doSendTokens}
sendingTokensLoader={sendingTokensLoader}
/>
<WalletContextProvider>
<Box padding={3}>
{type === 'connect' && (
<ConnectWallet />
)}
{/* {type === 'sendTokens' && (
<WalletContext.Provider value={{...WalletContext}}>
<SendTokes
// setRecipientAddress={setRecipientAddress}
// signerCosmosWasmClient={signerCosmosWasmClient}
// account={account}
// recipientAddress={recipientAddress}
/>
</WalletContext.Provider>
)}
{type === 'delegations' && (
<Delegations
delegations={delegations}
doDelegate={doDelegate}
delegationLoader={delegationLoader}
undeledationLoader={undeledationLoader}
doUndelegateAll={doUndelegateAll}
doWithdrawRewards={doWithdrawRewards}
withdrawLoading={withdrawLoading}
/>
)}
{log.length > 0 && (
<WalletContext.Provider value={WalletContext}>
<Delegations />
</WalletContext.Provider>
)} */}
{/* {log.length > 0 && (
<Box marginTop={3}>
<Typography variant="h5">Transaction Logs:</Typography>
{log}
</Box>
)}
</Box>
)} */}
</Box>
</WalletContextProvider>
);
};
@@ -1,74 +1,69 @@
import React from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { Coin } from '@cosmjs/stargate';
import Button from '@mui/material/Button';
import Paper from '@mui/material/Paper';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import TextField from '@mui/material/TextField';
import { useWalletContext } from '../context/wallet';
export const ConnectWallet = ({
setMnemonic,
connect,
mnemonic,
accountLoading,
clientLoading,
balanceLoading,
account,
balance,
connectButtonText,
}: {
setMnemonic: (value: string) => void;
connect: () => void;
mnemonic: string;
accountLoading: boolean;
clientLoading: boolean;
balanceLoading: boolean;
account: string;
balance: Coin;
connectButtonText: string;
}) => {
return (
<Paper style={{ marginTop: '1rem', padding: '1rem' }}>
<Typography variant="h5" textAlign="center">
Connect to your testnet account
</Typography>
<Box padding={3}>
<Typography variant="h6">Your testnet account:</Typography>
<Box marginY={3}>
<Typography variant="body1" marginBottom={3}>
Enter the mnemonic
</Typography>
<TextField
type="text"
placeholder="mnemonic"
onChange={(e) => setMnemonic(e.target.value)}
fullWidth
multiline
maxRows={4}
sx={{ marginBottom: 3 }}
/>
<Button
variant="outlined"
onClick={() => connect()}
disabled={!mnemonic || accountLoading || clientLoading || balanceLoading}
>
{connectButtonText}
</Button>
</Box>
{account && balance ? (
<Box>
<Typography variant="body1">Address: {account}</Typography>
<Typography variant="body1">
Balance: {balance?.amount} {balance?.denom}
</Typography>
</Box>
) : (
<Box>
<Typography variant="body1">Please, enter your mnemonic to receive your account information</Typography>
</Box>
)}
export const ConnectWallet = () => {
const { balance, balanceLoading, accountLoading, setConnectWithMnemonic, account, clientsAreLoading } =
useWalletContext();
const [mnemonic, setMnemonic] = useState<string>();
const [connectButtonText, setConnectButtonText] = useState<string>('Connect');
useEffect(() => {
if (accountLoading || clientsAreLoading || balanceLoading) {
setConnectButtonText('Loading...');
} else if (balance) {
setConnectButtonText('Connected');
}
setConnectButtonText('Connect');
}, [accountLoading, clientsAreLoading, balanceLoading]);
return (
<Paper style={{ marginTop: '1rem', padding: '1rem' }}>
<Typography variant="h5" textAlign="center">
Connect to your testnet account
</Typography>
<Box padding={3}>
<Typography variant="h6">Your testnet account:</Typography>
<Box marginY={3}>
<Typography variant="body1" marginBottom={3}>
Enter the mnemonic
</Typography>
<TextField
type="text"
placeholder="mnemonic"
onChange={(e) => setMnemonic(e.target.value)}
fullWidth
multiline
maxRows={4}
sx={{ marginBottom: 3 }}
/>
<Button
variant="outlined"
onClick={() => setConnectWithMnemonic(mnemonic)}
disabled={!mnemonic || accountLoading || clientsAreLoading || balanceLoading}
>
{connectButtonText}
</Button>
</Box>
</Paper>
);
};
{account && balance ? (
<Box>
<Typography variant="body1">Address: {account}</Typography>
<Typography variant="body1">
Balance: {balance?.amount} {balance?.denom}
</Typography>
</Box>
) : (
<Box>
<Typography variant="body1">Please, enter your mnemonic to receive your account information</Typography>
</Box>
)}
</Box>
</Paper>
);
};
@@ -5,104 +5,178 @@ import Box from '@mui/material/Box';
import { TableBody, TableCell, TableHead, TableRow, TextField, Typography } from '@mui/material';
import Table from '@mui/material/Table';
export const Delegations = ({
delegations,
doDelegate,
delegationLoader,
doUndelegateAll,
undeledationLoader,
doWithdrawRewards,
withdrawLoading,
}: {
delegations: any;
doDelegate: ({ mixId, amount }: { mixId: number; amount: number }) => void;
delegationLoader: boolean;
doUndelegateAll: () => void;
undeledationLoader: boolean;
doWithdrawRewards: () => void;
withdrawLoading: boolean;
}) => {
export const Delegations = () => {
const [delegationNodeId, setDelegationNodeId] = useState<string>();
const [amountToBeDelegated, setAmountToBeDelegated] = useState<string>();
const [log, setLog] = useState<React.ReactNode[]>([]);
const [delegations, setDelegations] = useState<any>();
const [delegationLoader, setDelegationLoader] = useState<boolean>(false);
const [undeledationLoader, setUndeledationLoader] = useState<boolean>(false);
const [withdrawLoading, setWithdrawLoading] = useState<boolean>(false);
// const getDelegations = useCallback(async () => {
// const newDelegations = await signerClient.getDelegatorDelegations({
// delegator: settings.address,
// });
// setDelegations(newDelegations);
// }, [signerClient]);
// // Start Undelgate All
// const doUndelegateAll = async () => {
// if (!signerClient) {
// return;
// }
// setUndeledationLoader(true);
// try {
// // eslint-disable-next-line no-restricted-syntax
// for (const delegation of delegations.delegations) {
// // eslint-disable-next-line no-await-in-loop
// await signerClient.undelegateFromMixnode({ mixId: delegation.mix_id }, 'auto');
// }
// } catch (error) {
// console.error(error);
// }
// setUndeledationLoader(false);
// };
// // End Undelgate All
// // Start Delegate
// const doDelegate = async ({ mixId, amount }: { mixId: number; amount: number }) => {
// if (!signerClient) {
// return;
// }
// setDelegationLoader(true);
// try {
// const res = await signerClient.delegateToMixnode({ mixId }, 'auto', undefined, [
// { amount: `${amount}`, denom: 'unym' },
// ]);
// console.log('res', res);
// setLog((prev) => [
// ...prev,
// <div key={JSON.stringify(res, null, 2)}>
// <code style={{ marginRight: '2rem' }}>{new Date().toLocaleTimeString()}</code>
// <pre>{JSON.stringify(res, null, 2)}</pre>
// </div>,
// ]);
// } catch (error) {
// console.error(error);
// }
// setDelegationLoader(false);
// };
// // End delegate
// // Start Withdraw Rewards
// const doWithdrawRewards = async () => {
// const delegatorAddress = '';
// const validatorAdress = '';
// const memo = 'test sending tokens';
// setWithdrawLoading(true);
// try {
// const res = await signerCosmosWasmClient.withdrawRewards(delegatorAddress, validatorAdress, 'auto', memo);
// setLog((prev) => [
// ...prev,
// <div key={JSON.stringify(res, null, 2)}>
// <code style={{ marginRight: '2rem' }}>{new Date().toLocaleTimeString()}</code>
// <pre>{JSON.stringify(res, null, 2)}</pre>
// </div>,
// ]);
// } catch (error) {
// console.error(error);
// }
// setWithdrawLoading(false);
// };
// // End Withdraw Rewards
// useEffect(() => {
// if (signerClient && !delegations) {
// getDelegations();
// }
// }, [signerClient, getDelegations, delegations]);
// return (
// <Paper style={{ marginTop: '1rem', padding: '1rem' }}>
// <Box padding={3}>
// <Typography variant="h6">Delegations</Typography>
// <Box marginY={3}>
// <Box marginY={3} display="flex" flexDirection="column">
// <Typography marginBottom={3} variant="body1">
// Make a delegation
// </Typography>
// <TextField
// type="text"
// placeholder="Mixnode ID"
// onChange={(e) => setDelegationNodeId(e.target.value)}
// size="small"
// />
// <Box marginTop={3} display="flex" justifyContent="space-between">
// <TextField
// type="text"
// placeholder="Amount"
// onChange={(e) => setAmountToBeDelegated(e.target.value)}
// size="small"
// />
// <Button
// variant="outlined"
// onClick={() =>
// doDelegate({ mixId: parseInt(delegationNodeId, 10), amount: parseInt(amountToBeDelegated, 10) })
// }
// disabled={delegationLoader}
// >
// {delegationLoader ? 'Delegation in process...' : 'Delegate'}
// </Button>
// </Box>
// </Box>
// </Box>
// <Box marginTop={3}>
// <Typography variant="body1">Your delegations</Typography>
// <Box marginBottom={3} display="flex" flexDirection="column">
// {!delegations?.delegations?.length ? (
// <Typography>You do not have delegations</Typography>
// ) : (
// <Box>
// <Table size="small">
// <TableHead>
// <TableRow>
// <TableCell>MixId</TableCell>
// <TableCell>Owner</TableCell>
// <TableCell>Amount</TableCell>
// <TableCell>Cumulative Reward Ratio</TableCell>
// </TableRow>
// </TableHead>
// <TableBody>
// {delegations?.delegations.map((delegation: any) => (
// <TableRow key={delegation.mix_id}>
// <TableCell>{delegation.mix_id}</TableCell>
// <TableCell>{delegation.owner}</TableCell>
// <TableCell>{delegation.amount.amount}</TableCell>
// <TableCell>{delegation.cumulative_reward_ratio}</TableCell>
// </TableRow>
// ))}
// </TableBody>
// </Table>
// </Box>
// )}
// </Box>
// {delegations && (
// <Box marginBottom={3}>
// <Button variant="outlined" onClick={() => doUndelegateAll()} disabled={undeledationLoader}>
// {undeledationLoader ? 'Undelegating...' : 'Undelegate All'}
// </Button>
// </Box>
// )}
// <Box>
// <Button variant="outlined" onClick={() => doWithdrawRewards()} disabled={withdrawLoading}>
// {withdrawLoading ? 'Doing withdraw...' : 'Withdraw rewards'}
// </Button>
// </Box>
// </Box>
// </Box>
// </Paper>
// );
return (
<Paper style={{ marginTop: '1rem', padding: '1rem' }}>
<Box padding={3}>
<Typography variant="h6">Delegations</Typography>
<Box marginY={3}>
<Box marginY={3} display="flex" flexDirection="column">
<Typography marginBottom={3} variant="body1">
Make a delegation
</Typography>
<TextField
type="text"
placeholder="Mixnode ID"
onChange={(e) => setDelegationNodeId(e.target.value)}
size="small"
/>
<Box marginTop={3} display="flex" justifyContent="space-between">
<TextField
type="text"
placeholder="Amount"
onChange={(e) => setAmountToBeDelegated(e.target.value)}
size="small"
/>
<Button
variant="outlined"
onClick={() =>
doDelegate({ mixId: parseInt(delegationNodeId, 10), amount: parseInt(amountToBeDelegated, 10) })
}
disabled={delegationLoader}
>
{delegationLoader ? 'Delegation in process...' : 'Delegate'}
</Button>
</Box>
</Box>
</Box>
<Box marginTop={3}>
<Typography variant="body1">Your delegations</Typography>
<Box marginBottom={3} display="flex" flexDirection="column">
{!delegations?.delegations?.length ? (
<Typography>You do not have delegations</Typography>
) : (
<Box>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>MixId</TableCell>
<TableCell>Owner</TableCell>
<TableCell>Amount</TableCell>
<TableCell>Cumulative Reward Ratio</TableCell>
</TableRow>
</TableHead>
<TableBody>
{delegations?.delegations.map((delegation: any) => (
<TableRow key={delegation.mix_id}>
<TableCell>{delegation.mix_id}</TableCell>
<TableCell>{delegation.owner}</TableCell>
<TableCell>{delegation.amount.amount}</TableCell>
<TableCell>{delegation.cumulative_reward_ratio}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Box>
)}
</Box>
{delegations && (
<Box marginBottom={3}>
<Button variant="outlined" onClick={() => doUndelegateAll()} disabled={undeledationLoader}>
{undeledationLoader ? 'Undelegating...' : 'Undelegate All'}
</Button>
</Box>
)}
<Box>
<Button variant="outlined" onClick={() => doWithdrawRewards()} disabled={withdrawLoading}>
{withdrawLoading ? 'Doing withdraw...' : 'Withdraw rewards'}
</Button>
</Box>
</Box>
</Box>
</Paper>
);
<Box>Hello</Box>
)
};
@@ -1,45 +1,94 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import Button from '@mui/material/Button';
import Paper from '@mui/material/Paper';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import TextField from '@mui/material/TextField';
import { useWalletContext } from '../context/wallet';
export const SendTokes = ({
setRecipientAddress,
doSendTokens,
sendingTokensLoader,
// setRecipientAddress,
// signerCosmosWasmClient,
// account,
// recipientAddress,
}: {
setRecipientAddress: (value: string) => void;
doSendTokens: (amount: string) => void;
sendingTokensLoader: boolean;
// setRecipientAddress: (value: string) => void;
// signerCosmosWasmClient: any;
// account: string;
// recipientAddress: string;
}) => {
const { cosmWasmSigner, cosmWasmSignerClient, nymWasmSignerClient, setConnectWithMnemonic } = useWalletContext();
const [recipientAddress, setRecipientAddress] = useState<string>('');
const [tokensToSend, setTokensToSend] = useState<string>();
const [sendingTokensLoader, setSendingTokensLoader] = useState<boolean>(false);
const [log, setLog] = useState<React.ReactNode[]>([]);
// Sending tokens
// const doSendTokens = async () => {
// const memo = 'test sending tokens';
// setSendingTokensLoader(true);
// try {
// console.log('signerCosmosWasmClient', signerCosmosWasmClient);
// const res = await signerCosmosWasmClient.sendTokens(
// account,
// recipientAddress,
// [{ amount: tokensToSend, denom: 'unym' }],
// 'auto',
// memo,
// );
// setLog((prev) => [
// ...prev,
// <div key={JSON.stringify(res, null, 2)}>
// <code style={{ marginRight: '2rem' }}>{new Date().toLocaleTimeString()}</code>
// <pre>{JSON.stringify(res, null, 2)}</pre>
// </div>,
// ]);
// } catch (error) {
// console.error(error);
// }
// setSendingTokensLoader(false);
// };
// End send tokens
// console.log('signerCosmosWasmClient', signerCosmosWasmClient);
// useEffect(() => {
// console.log('signerCosmosWasmClient', signerCosmosWasmClient, 'account', account);
// }, [signerCosmosWasmClient, account]);
return (
<Paper style={{ marginTop: '1rem', padding: '1rem' }}>
<Box padding={3}>
<Typography variant="h6">Send Tokens</Typography>
<Box marginTop={3} display="flex" flexDirection="column">
<TextField
type="text"
placeholder="Recipient Address"
onChange={(e) => setRecipientAddress(e.target.value)}
size="small"
/>
<Box marginY={3} display="flex" justifyContent="space-between">
<Box>
<Paper style={{ marginTop: '1rem', padding: '1rem' }}>
<Box padding={3}>
<Typography variant="h6">Send Tokens</Typography>
<Box marginTop={3} display="flex" flexDirection="column">
<TextField
type="text"
placeholder="Amount"
onChange={(e) => setTokensToSend(e.target.value)}
placeholder="Recipient Address"
onChange={(e) => setRecipientAddress(e.target.value)}
size="small"
/>
<Button variant="outlined" onClick={() => doSendTokens(tokensToSend)} disabled={sendingTokensLoader}>
{sendingTokensLoader ? 'Sending...' : 'SendTokens'}
</Button>
<Box marginY={3} display="flex" justifyContent="space-between">
<TextField
type="text"
placeholder="Amount"
onChange={(e) => setTokensToSend(e.target.value)}
size="small"
/>
{/* <Button variant="outlined" onClick={() => doSendTokens()} disabled={sendingTokensLoader}>
{sendingTokensLoader ? 'Sending...' : 'Send tokens'}
</Button> */}
</Box>
</Box>
</Box>
</Box>
</Paper>
</Paper>
{log.length > 0 && (
<Box marginTop={3}>
<Typography variant="h5">Transaction Logs:</Typography>
{log}
</Box>
)}
</Box>
);
};
};