Ethereum Boilerplate Questions

I get the following below

How can switch chain in trust wallet with boilerplate please help me.

Watch for github comments only. Do not update the whole project.

Thank you! But that line does not exist in my MenuItems.jsx file…?

Hello,
After adding a custom token the Dex is giving a popup error 400 when trying to swap to the custom token. And when trying to swap any other token it gives a “Swap Complete” popup but doesn’t actually complete the swap. Any help appreciated.

You can test at: https://monkeyninja.io/1inch

Thanks!

Hey @jtran1047

Try to change your package.json to:

"start": "react-scripts --openssl-legacy-provider start"

You cannot make this. TrustWallet doesn’t have active chain like Metamask.

Hey @flyingsockwithsugar

You can edit the ethereum-boilerplate/src/components/Contract/

More responsive design is now in progress. Fo sure you can, the code is absolutely open, you can edit it any way you want

No

Hey @pkgujjar

The is a table component. But yeah, now I can see it may be confusing. In the coming versions, we will make separate ERC20Balance for one token and ERC20Balances for all

For now you can filter a result from useERC20Balances()

No worries. Add this line overflowedIndicator="Your Title Goes Here" after this line mode="horizontal" in your MenuItems.jsx.

I think you are misunderstanding. The indicator or icon is there. I just want to know how to change it to a different icon.

You can see here: https://monkeyninja.io

No, just add this overflowedIndicator="Your Title Goes Here" and it will replace it for whatever you want.

1 Like

Can you post your code? so I can review it.

1 Like
import { useState, useEffect, useMemo } from "react";
import { useMoralis } from "react-moralis";
import InchModal from "./components/InchModal";
import useInchDex from "hooks/useInchDex";
import { Button, Card, Image, Input, InputNumber, Modal } from "antd";
import Text from "antd/lib/typography/Text";
import { ArrowDownOutlined } from "@ant-design/icons";
import { useTokenPrice } from "react-moralis";
import { tokenValue } from "helpers/formatters";
import { getWrappedNative } from "helpers/networks";
// import { useOneInchQuote } from "react-moralis";

const styles = {
  card: {
    maxWidth: "430px",
    minWidth: "360px",
    boxShadow: "0 0.5rem 1.2rem rgb(189 197 209 / 20%)",
    border: "0",
    borderRadius: "1rem",
    fontSize: "16px",
    fontWeight: "500",
    color: "#f4db73",
    margin: "20px auto 40px",
    background: "#222",
  },
  input: {
    padding: "0",
    fontWeight: "500",
    fontSize: "23px",
    display: "block",
    width: "100%",
    color: "#fff",
  },
  priceSwap: {
    display: "flex",
    justifyContent: "space-between",
    fontSize: "15px",
    color: "#fff",
    marginTop: "8px",
    padding: "0 10px",
  },
  priceEst: {
    color: "#fff",
  },
};

const nativeAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";

const chainIds = {
  "0x1": "eth",
  "0x38": "bsc",
  "0x89": "polygon",
};

const getChainIdByName = (chainName) => {
  for (let chainId in chainIds) {
    if (chainIds[chainId] === chainName) return chainId;
  }
};

const IsNative = (address) => address === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";

function DEX({ chain, customTokens = {
  "0xe7541aa266fa18edc1b4cfd766b814ec25d9c937": {
    address: "0xe7541aa266fa18edc1b4cfd766b814ec25d9c937",
    decimals: 18,
    logoURI: "https://monkeyninja.io/static/media/token-01.png",
    name: "Okane",
    symbol: "Okane",
  },
}}) {
  const { trySwap, tokenList, getQuote } = useInchDex(chain = 'polygon');

  const { Moralis, isInitialized, chainId } = useMoralis();
  const [isFromModalActive, setFromModalActive] = useState(false);
  const [isToModalActive, setToModalActive] = useState(false);
  const [fromToken, setFromToken] = useState();
  const [toToken, setToToken] = useState();
  const [fromAmount, setFromAmount] = useState();
  const [quote, setQuote] = useState();
  const [currentTrade, setCurrentTrade] = useState();
  const { fetchTokenPrice } = useTokenPrice();
  const [tokenPricesUSD, setTokenPricesUSD] = useState({});

  const tokens = useMemo(() => {
    return { ...customTokens, ...tokenList };
  }, [customTokens, tokenList]);

  const fromTokenPriceUsd = useMemo(
    () => (tokenPricesUSD?.[fromToken?.["address"]] ? tokenPricesUSD[fromToken?.["address"]] : null),
    [tokenPricesUSD, fromToken]
  );

  const toTokenPriceUsd = useMemo(
    () => (tokenPricesUSD?.[toToken?.["address"]] ? tokenPricesUSD[toToken?.["address"]] : null),
    [tokenPricesUSD, toToken]
  );

  const fromTokenAmountUsd = useMemo(() => {
    if (!fromTokenPriceUsd || !fromAmount) return null;
    return `~$ ${(fromAmount * fromTokenPriceUsd).toFixed(4)}`;
  }, [fromTokenPriceUsd, fromAmount]);

  const toTokenAmountUsd = useMemo(() => {
    if (!toTokenPriceUsd || !quote) return null;
    return `~$ ${(Moralis.Units.FromWei(quote?.toTokenAmount, quote?.toToken?.decimals) * toTokenPriceUsd).toFixed(4)}`;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [toTokenPriceUsd, quote]);

  // tokenPrices
  useEffect(() => {
    if (!isInitialized || !fromToken || !chain) return null;
    const validatedChain = chain ? getChainIdByName(chain) : chainId;
    const tokenAddress = IsNative(fromToken["address"]) ? getWrappedNative(validatedChain) : fromToken["address"];
    fetchTokenPrice({
      params: { chain: validatedChain, address: tokenAddress },
      onSuccess: (price) =>
        setTokenPricesUSD({
          ...tokenPricesUSD,
          [fromToken["address"]]: price["usdPrice"],
        }),
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [chain, isInitialized, fromToken]);

  useEffect(() => {
    if (!isInitialized || !toToken || !chain) return null;
    const validatedChain = chain ? getChainIdByName(chain) : chainId;
    const tokenAddress = IsNative(toToken["address"]) ? getWrappedNative(validatedChain) : toToken["address"];
    fetchTokenPrice({
      params: { chain: validatedChain, address: tokenAddress },
      onSuccess: (price) =>
        setTokenPricesUSD({
          ...tokenPricesUSD,
          [toToken["address"]]: price["usdPrice"],
        }),
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [chain, isInitialized, toToken]);

  useEffect(() => {
    if (!tokens || fromToken) return null;
    setFromToken(tokens[nativeAddress]);
  }, [tokens, fromToken]);

  const ButtonState = useMemo(() => {
    // if (chainIds?.[chainId] !== chain) return { isActive: false, text: `Switch to ${chain}` };
    if (chainIds?.[chainId] !== 'polygon') return { isActive: false, text: `Switch to Polygon` };

    if (!fromAmount) return { isActive: false, text: "Enter an Amount" };
    if (fromAmount && currentTrade) return { isActive: true, text: "Swap" };
    return { isActive: false, text: "Select Tokens" };
  }, [fromAmount, currentTrade, chainId/*, chain*/]);

  useEffect(() => {
    if (fromToken && toToken && fromAmount) setCurrentTrade({ fromToken, toToken, fromAmount, chain });
  }, [toToken, fromToken, fromAmount, chain]);

  useEffect(() => {
    if (currentTrade) getQuote(currentTrade).then((quote) => setQuote(quote));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentTrade]);

  const PriceSwap = () => {
    const Quote = quote;
    if (!Quote || !tokenPricesUSD?.[toToken?.["address"]]) return null;
    if (Quote?.statusCode === 400) return <>{Quote.message}</>;
    console.log(Quote);
    const { fromTokenAmount, toTokenAmount } = Quote;
    const { symbol: fromSymbol } = fromToken;
    const { symbol: toSymbol } = toToken;
    const pricePerToken = parseFloat(
      tokenValue(fromTokenAmount, fromToken["decimals"]) / tokenValue(toTokenAmount, toToken["decimals"])
    ).toFixed(6);
    return (
      <Text style={styles.priceSwap}>
        Price:{" "}
        <Text style={styles.priceEst}>{`1 ${toSymbol} = ${pricePerToken} ${fromSymbol} ($${tokenPricesUSD[[toToken["address"]]].toFixed(6)})`}</Text>
      </Text>
    );
  };

  return (
    <>
      <h1 style={{ textAlign: "center", paddingTop: "7rem" }}>Ninja Swap</h1>
      {/*<h4 style={{ textAlign: "center" }}>Please make sure your wallet is connected to the Polygon Mainnet.</h4>*/}
      <Card style={styles.card} bodyStyle={{ padding: "8px" }}>
        <Card style={{ borderRadius: "0.5rem", background: "#333" }} bodyStyle={{ padding: "0.8rem" }}>
          <div style={{ marginBottom: "5px", fontSize: "14px", color: "#fff" }}>From</div>
          <div
            style={{
              display: "flex",
              flexFlow: "row nowrap",
            }}
          >
            <div>
              <InputNumber
                bordered={false}
                placeholder="0.00"
                style={{ ...styles.input, marginLeft: "-10px" }}
                onChange={setFromAmount}
                value={fromAmount}
              />
              <Text style={{ fontWeight: "600", color: "rgb(69, 184, 0)" }}>{fromTokenAmountUsd}</Text>
            </div>
            <Button
              style={{
                height: "fit-content",
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                borderRadius: "4px",
                padding: "5px 10px",
                fontWeight: "500",
                fontSize: "18px",
                gap: "7px",
                border: "none",
              }}
              onClick={() => setFromModalActive(true)}
            >
              {fromToken ? (
                <Image
                  src={fromToken?.logoURI || "https://etherscan.io/images/main/empty-token.png"}
                  alt="nologo"
                  width="30px"
                  preview={false}
                  style={{ borderRadius: "15px" }}
                />
              ) : (
                <span>Select a Token</span>
              )}
              <span>{fromToken?.symbol}</span>
              <Arrow />
            </Button>
          </div>
        </Card>
        <div style={{ display: "flex", justifyContent: "center", margin: "-15px 0 3px" }}>
          <ArrowDownOutlined style={{ zIndex: "1", }} />
        </div>
        <Card style={{ borderRadius: "0.5rem", background: "#333" }} bodyStyle={{ padding: "0.8rem" }}>
          <div style={{ marginBottom: "5px", fontSize: "14px", color: "#fff" }}>To</div>
          <div
            style={{
              display: "flex",
              flexFlow: "row nowrap",
            }}
          >
            <div>
              <Input
                className="dexInput"
                bordered={false}
                placeholder="0.00"
                style={styles.input}
                readOnly
                value={quote ? Moralis.Units.FromWei(quote?.toTokenAmount, quote?.toToken?.decimals).toFixed(6) : ""}
              />
              <Text style={{ fontWeight: "600", color: "rgb(69, 184, 0)" }}>{toTokenAmountUsd}</Text>
            </div>
            <Button
              style={{
                height: "fit-content",
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                borderRadius: "4px",
                padding: "5px 10px",
                fontWeight: "500",
                fontSize: "18px",
                gap: "7px",
                border: "none",
              }}
              onClick={() => setToModalActive(true)}
              type={toToken ? "default" : "primary"}
            >
              {toToken ? (
                <Image
                  src={toToken?.logoURI || "https://etherscan.io/images/main/empty-token.png"}
                  alt="nologo"
                  width="30px"
                  preview={false}
                  style={{ borderRadius: "15px" }}
                />
              ) : (
                <span>Select A Token</span>
              )}
              <span>{toToken?.symbol}</span>
              <Arrow />
            </Button>
          </div>
        </Card>
        {quote && (
          <div>
            <Text
              style={{
                display: "flex",
                justifyContent: "space-between",
                fontSize: "15px",
                color: "#fff",
                marginTop: "8px",
                padding: "0 10px",
                borderTop: "4px dotted #fff",
                paddingTop: "8px",
              }}
            >
              Estimated Gas: <Text style={{ color: "#fff" }}>{quote?.estimatedGas}</Text>
            </Text>
            <PriceSwap />
          </div>
        )}
        <Button
          type="primary"
          size="large"
          style={{
            width: "100%",
            marginTop: "15px",
            borderRadius: "4px",
            border: "0",
            height: "50px",
            background: "#ffb148",
            color: "#fff",
            textTransform: "uppercase",
            fontWeight: "bold",
          }}
          onClick={() => trySwap(currentTrade)}
          disabled={!ButtonState.isActive}
        >
          {ButtonState.text}
        </Button>
      </Card>
      <Modal
        title="Select a Token"
        visible={isFromModalActive}
        onCancel={() => setFromModalActive(false)}
        bodyStyle={{ padding: 0 }}
        maxWidth="450px"
        minWidth="360px"
        footer={null}
      >
        <InchModal
          open={isFromModalActive}
          onClose={() => setFromModalActive(false)}
          setToken={setFromToken}
          tokenList={tokens}
        />
      </Modal>
      <Modal
        title="Select a Token"
        visible={isToModalActive}
        onCancel={() => setToModalActive(false)}
        bodyStyle={{ padding: 0 }}
        maxWidth="450px"
        minWidth="360px"
        footer={null}
      >
        <InchModal
          open={isToModalActive}
          onClose={() => setToModalActive(false)}
          setToken={setToToken}
          tokenList={tokens} />
      </Modal>
    </>
  );
}

export default DEX;

const Arrow = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    strokeWidth="2"
    stroke="currentColor"
    fill="none"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    <path stroke="none" d="M0 0h24v24H0z" fill="none" />
    <polyline points="6 9 12 15 18 9" />
  </svg>
);

Oooooh excellent! Can I give it an image file path or what type of attribute does it need?

I think you can use this : url(“img.png”)’,`

That doesn’t seem to work…

Hi Mejmerlin, Have u successfully created DEX? I am working on creating dex as well

Somehow posted the wrong url. Check this https://ant.design/components/menu/

I am assuming its 1inch issue since I am getting this error
https://api.1inch.exchange/v3.0/1/swap