Developers
Live Playground
3.2. Basic wallet operations

Wallet

🚫

The TypeScript SDK is currently not avaliable to use: a network upgrade elsewhere has caused a problem which is not currently fixed. TS SDK Clients are not able to connect to the network.

When the issue is resolved, this will be reflected in the documentation.

Thanks for your patience!

Here's a small wallet example using testnet for you to test out!

Connect to your testnet account
Your testnet account:

Enter the mnemonic

Please, enter your mnemonic to receive your account information

FormattedWalletConnectCode.tsx
import React 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';
 
// Connect method on Parent Component
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);
};
 
// Get Balance on Parent Component
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 getClients = async () => {
  setClientLoading(true);
  try {
    setSignerCosmosWasmClient(await fetchSignerCosmosWasmClient(mnemonic));
    setSignerClient(await fetchSignerClient(mnemonic));
  } catch (error) {
    console.error(error);
  }
  setClientLoading(false);
};
 
const connect = () => {
  getSignerAccount();
  getClients();
};
 
// Get Signner Account on Parent Component
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);
};
 
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 account
      </Typography>
      <Box padding={3}>
        <Typography variant="h6">Your 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>
        )}
      </Box>
    </Paper>
  );
};
Send Tokens
FormattedWalletSendTokensCode.tsx
import React, { useState } 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';
 
// Send tokens on Parent component
  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);
  };
 
export const SendTokes = ({
  setRecipientAddress,
  doSendTokens,
  sendingTokensLoader,
}: {
  setRecipientAddress: (value: string) => void;
  doSendTokens: (amount: string) => void;
  sendingTokensLoader: boolean;
}) => {
  const [tokensToSend, setTokensToSend] = useState<string>();
 
  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">
            <TextField
              type="text"
              placeholder="Amount"
              onChange={(e) => setTokensToSend(e.target.value)}
              size="small"
            />
            <Button variant="outlined" onClick={() => doSendTokens(amount)} disabled={sendingTokensLoader}>
              {sendingTokensLoader ? 'Sending...' : 'SendTokens'}
            </Button>
          </Box>
        </Box>
      </Box>
    </Paper>
  );
};
Delegations

Make a delegation

Your delegations:

You do not have delegations

FormattedWalletDelegationsCode.tsx
import React from 'react';
import Button from '@mui/material/Button';
import Paper from '@mui/material/Paper';
import Box from '@mui/material/Box';
import { TableBody, TableCell, TableHead, TableRow, TextField, Typography } from '@mui/material';
import Table from '@mui/material/Table';
 
// Get Delegations on parent component
  const getDelegations = useCallback(async () => {
    const newDelegations = await signerClient.getDelegatorDelegations({
      delegator: settings.address,
    });
    setDelegations(newDelegations);
  }, [signerClient]);
 
// Make a Delegation on parent component
  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);
  };
 
  // Undelegate All on Parent Component
  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);
  };
 
  // Withdraw Rewards on Parent Component
  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);
  };
 
import React, { useState } from 'react';
import Button from '@mui/material/Button';
import Paper from '@mui/material/Paper';
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;
}) => {
  const [delegationNodeId, setDelegationNodeId] = useState<string>();
  const [amountToBeDelegated, setAmountToBeDelegated] = useState<string>();
 
  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>
  );
};