In this example we’re going to mint some tokens from one contract and stake them in another using transaction kit.

This example will show how to do custom contract calls, show how to approve ERC20 tokens, and show how to batch transactions.

You can check how to do these things within the components we will create, and then we’ll call these components in App.js

We have a code sandbox for this example which you can fork here.

Start off by creating a react app, you can see how to do this here

Make sure you have the Transaction Kit and Ethers (version 5.4.0) packages installed, then we’ll edit two files and create two more as components. App.js and index.js.

index.js

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import { EtherspotTransactionKit } from "@etherspot/transaction-kit";
import * as ethers from "ethers";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

const randomWallet = ethers.Wallet.createRandom();
const providerWallet = new ethers.Wallet(randomWallet.privateKey);

console.log(providerWallet);

root.render(
  <StrictMode>
    <EtherspotTransactionKit provider={providerWallet} chainId={80001}>
      <App />
    </EtherspotTransactionKit>
  </StrictMode>
);

App.js

import { Typography, Container, Box, Paper } from "@mui/material";
import { useWalletAddress } from "@etherspot/transaction-kit";
import { useEffect, useState } from "react";
import MintTktTokens from "./components/MintTktTokens/MintTktTokens";
import StakeTktTokens from "./components/StakeTktTokens/StakeTktTokens";

export default function App() {
  const [hasSentMintTx, setHasSentMintTx] = useState(false);
  const [hasSentStakingTx, setHasSentStakingTx] = useState(false);
  const mumbaiAddress = useWalletAddress("etherspot-prime", 80001);
  const [mumbaiSmartWalletAddress, setMumbaiSmartWalletAddress] = useState(
    false
  );

  useEffect(() => {
    console.log("etherspotAddresses", mumbaiAddress);

    const fetchMumbaiSmartWallet = () => {
      setMumbaiSmartWalletAddress(mumbaiAddress);
    };

    fetchMumbaiSmartWallet();
  }, [mumbaiAddress, mumbaiSmartWalletAddress]);

  const onSentStakingTransactionReceiver = (e) => {
    console.log("Sent Staking Transaction:", e);
    setHasSentStakingTx(true);
  };

  const onSentMintTransactionReceiver = (e) => {
    console.log("Sent Mint Transaction:", e);
    setHasSentMintTx(true);
  };

  return (
    <Container>
      <Typography variant="h3">Transaction Kit</Typography>
      <Typography variant="h4">Staking Example</Typography>

      <Box m={2} />

      {mumbaiSmartWalletAddress ? (
        <MintTktTokens
          hasSentMintTx={hasSentMintTx}
          onSentMintTransactionReceiver={onSentMintTransactionReceiver}
          mumbaiSmartWalletAddress={mumbaiSmartWalletAddress}
        />
      ) : null}

      <Box m={2} />

      {hasSentMintTx ? (
        <StakeTktTokens
          hasSentMintTx={hasSentMintTx}
          hasSentStakingTx={hasSentStakingTx}
          onSentStakingTransactionReceiver={onSentStakingTransactionReceiver}
          mumbaiSmartWalletAddress={mumbaiSmartWalletAddress}
        />
      ) : null}

      <Box m={4} />

      <Paper sx={{ p: 2 }}>
        <Typography textAlign={"center"} variant="subtitle2">
          Etherspot Smart Wallet address: {mumbaiSmartWalletAddress}
        </Typography>
        <Typography textAlign={"center"} variant="subtitle2">
          TKT Token Contract: {"0x2A9bb3fB4FBF8e536b9a6cBEbA33C4CD18369EaF"}
        </Typography>
        <Typography textAlign={"center"} variant="subtitle2">
          TKT Staking Contract: {"0x0493b9a21dE42546B2E3687Da683D0B7B6ec2180"}
        </Typography>
      </Paper>
    </Container>
  );
}

Now we want to create a directory called components in the same directory as index.js and App.js

Within components, create a directory called MintTktTokens and within that create a file called MintTktTokens.js

MintTktTokens.js

import { Typography, Paper, Button, Grid, Alert } from "@mui/material";
import {
  EtherspotContractTransaction,
  EtherspotBatches,
  EtherspotBatch,
  useEtherspotTransactions
} from "@etherspot/transaction-kit";
import { utils } from "ethers";

export default function MintTktTokens(props) {
  const { estimate, send } = useEtherspotTransactions();

  const estimateAndMint = async () => {
    const estimateData = await estimate();
    console.log("Estimate Data:", estimateData);

    if (JSON.stringify(estimateData).includes("reverted")) {
      alert("Tx reverted! No gas token in account");
      return;
    }

    const sendData = await send();
    console.log("Send Data:", sendData);
  };

  return (
    <>
      {props.hasSentMintTx ? (
        <Alert severity="success">
          The transaction to mint TKT tokens was sent to Etherspot
        </Alert>
      ) : (
        <EtherspotBatches
          via={"etherspot-prime"}
          onEstimated={props.onEstimateReceiver}
          onSent={props.onSentMintTransactionReceiver}
        >
          <EtherspotBatch>
            <EtherspotContractTransaction
              contractAddress={"0x2A9bb3fB4FBF8e536b9a6cBEbA33C4CD18369EaF"}
              abi={["function mint(address, uint)"]}
              methodName={"mint"}
              params={[props.mumbaiSmartWalletAddress, utils.parseEther("10")]}
            >
              <Paper sx={{ p: 2 }} variant={"outlined"}>
                <Typography align="center">
                  First, let's mint some TKT tokens into your Etherspot Smart
                  Wallet on Mumbai:
                  <pre>{props.mumbaiSmartWalletAddress}</pre>
                </Typography>

                <Grid container justifyContent="center">
                  <Button onClick={() => estimateAndMint()} variant="outlined">
                    Mint TKT Tokens
                  </Button>
                </Grid>
              </Paper>
            </EtherspotContractTransaction>
          </EtherspotBatch>
        </EtherspotBatches>
      )}
    </>
  );
}

Also within that create a folder called StakeTktTokens and within that create a file called StakeTktTokens.js

StakeTktTokens.js

import { Typography, Paper, Button, Grid, Alert } from "@mui/material";
import {
  EtherspotContractTransaction,
  EtherspotApprovalTransaction,
  EtherspotBatches,
  EtherspotBatch,
  useEtherspotTransactions
} from "@etherspot/transaction-kit";
import { utils } from "ethers";

export default function StakeTktTokens(props) {
  const { estimate, send } = useEtherspotTransactions();

  const estimateAndStake = async () => {
    const estimateData = await estimate();
    console.log("Stake Estimate Data:", estimateData);

    if (JSON.stringify(estimateData).includes("reverted")) {
      alert("Tx reverted!");
      return;
    }

    const sendData = await send();
    console.log("Stake Send Data:", sendData);
  };

  return (
    <>
      {props.hasSentStakingTx ? (
        <Alert severity="success">
          You have sent the staking transaction to Etherspot!
        </Alert>
      ) : (
        <EtherspotBatches
          via={"etherspot-prime"}
          onEstimated={props.onEstimateReceiver}
          onSent={props.onSentStakingTransactionReceiver}
        >
          <EtherspotBatch>
            <EtherspotApprovalTransaction
              tokenAddress={"0x2A9bb3fB4FBF8e536b9a6cBEbA33C4CD18369EaF"}
              receiverAddress={"0x0493b9a21dE42546B2E3687Da683D0B7B6ec2180"}
              value={"10"}
            />
            <EtherspotContractTransaction
              contractAddress={"0x0493b9a21dE42546B2E3687Da683D0B7B6ec2180"}
              abi={["function stake(uint)"]}
              methodName={"stake"}
              params={[utils.parseEther("10")]}
            >
              <Paper sx={{ p: 2 }} variant={"outlined"}>
                <Typography align="center">
                  Next, lets stake these tokens into an example staking contract
                  we have created.
                </Typography>

                <Grid container justifyContent="center">
                  <Button onClick={() => estimateAndStake()} variant="outlined">
                    Stake TKT Tokens
                  </Button>
                </Grid>
              </Paper>
            </EtherspotContractTransaction>
          </EtherspotBatch>
        </EtherspotBatches>
      )}
    </>
  );
}