adding a react context... imposible to avoid it at the end : (
This commit is contained in:
@@ -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>;
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user