Add/Import cusotm token on dex

so passing that code already working using your own token?

Yes just passing that info makes it work, but that was just me testing. this is what the code looked like before:

InchModal.jsk

onClick={() => {
              setToken(tokenList[token]);
                console.log(tokenList[token])
                onClose();
              }}

so my code just forced my token info in no matter what token I clicked on. now that the test worked I would say push your token info into the tokenList and it will appear in the list of choices.

i see
i just want it to be a default token
but i will try that also how it work on dex

btw is that the complete info how to implement that ?

I made a custom component for doing this:

import InchDexCustom from "components/InchDex/InchDexCustom";

<InchDexCustom chain="bsc" toTokenAddress="0xc66c...f9b2de" slippage={12}/>

How to use:

Change line 78 of useInchDex.js hook:

from
slippage: 1,

to
slippage: params.newslippage ? params.newslippage : 1,

Add this file to the InchDex folder in components:

InchDexCustom.jsx

import { useState, useEffect, useMemo } from "react";
import { useMoralis, useWeb3Contract } from "react-moralis";
import { useMoralisDapp } from "providers/MoralisDappProvider/MoralisDappProvider";
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 "hooks/useTokenPrice";
import { tokenValue } from "helpers/formatters";
//import erc20Abi from "./contractAbi/standardErc20Abi" 
// import { useOneInchQuote } from "react-moralis";

const styles = {
  card: {
    width: "430px",
    boxShadow: "0 0.5rem 1.2rem rgb(189 197 209 / 20%)",
    border: "1px solid #e7eaf3",
    borderRadius: "1rem",
    fontSize: "16px",
    fontWeight: "500",
  },
  input: {
    padding: "0",
    fontWeight: "500",
    fontSize: "23px",
    display: "block",
    width: "100%",
  },
  priceSwap: {
    display: "flex",
    justifyContent: "space-between",
    fontSize: "15px",
    color: "#434343",
    marginTop: "8px",
    padding: "0 10px",
  },
};

const nativeAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";

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

function InchDexCustom({ chain, toTokenAddress, slippage }) {
  const { trySwap, tokenList, getQuote } = useInchDex(chain);
console.log(tokenList)
  const { Moralis, isInitialized } = useMoralis();
  const { chainId } = useMoralisDapp();
  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({});
  console.log("fromToken", fromToken);
  const options = { chain: chain, addresses: toTokenAddress }; //--------------------
  const [ tokendata, settokendata] = useState([])
  const [newslippage, setSlippage] = useState(slippage)
  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]);


   function changeSlippage(e){
    setSlippage(e.target.value);
   }
  // tokenPrices
  useEffect(() => {
    if (!isInitialized || !fromToken || !chain) return null;
    fetchTokenPrice({ chain: chain, address: fromToken[["address"]] }).then((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;
    fetchTokenPrice({ chain: chain, address: toToken[["address"]] }).then((price) =>
      setTokenPricesUSD({
        ...tokenPricesUSD,
        [toToken["address"]]: price["usdPrice"],
      })
    );
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [chain, isInitialized, toToken]);

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


  useEffect(async() => {
    const result =await Moralis.Web3API.token.getTokenMetadata(options)
    settokendata(result);
    if(!toToken ){
      setToToken(result[0]);
    }
   
     
    //.then(setCurrentTrade( fromToken, toTokenAddress, fromAmount, chain))
    console.log(result);
    if (tokendata){
      
    }
  }, [toToken]);

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

    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, newslippage });
  }, [toToken, fromToken, fromAmount, chain, newslippage]);

  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>{`1 ${toSymbol} = ${pricePerToken} ${fromSymbol} ($${tokenPricesUSD[[toToken["address"]]].toFixed(
          6
        )})`}</Text>
      </Text>
    );
  };

  return (
    <>
      <Card style={styles.card} bodyStyle={{ padding: "18px" }}>
        <Card style={{ borderRadius: "1rem" }} bodyStyle={{ padding: "0.8rem" }}>
          <div style={{ marginBottom: "5px", fontSize: "14px", color: "#434343" }}>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: "#434343" }}>{fromTokenAmountUsd}</Text>
            </div>
            <Button
              style={{
                height: "fit-content",
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                borderRadius: "0.6rem",
                padding: "5px 10px",
                fontWeight: "500",
                fontSize: "17px",
                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", padding: "10px" }}>
          <ArrowDownOutlined />
        </div>
        <Card style={{ borderRadius: "1rem" }} bodyStyle={{ padding: "0.8rem" }}>
          <div style={{ marginBottom: "5px", fontSize: "14px", color: "#434343" }}>To</div>
          <div
            style={{
              display: "flex",
              flexFlow: "row nowrap",
            }}
          >
            <div>
              <Input
                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: "#434343" }}>{toTokenAmountUsd}</Text>
            </div>
            <Button
              style={{
                height: "fit-content",
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                borderRadius: "0.6rem",
                padding: "5px 10px",
                fontWeight: "500",
                fontSize: "17px",
                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: "#434343",
                marginTop: "8px",
                padding: "0 10px",
              }}
            >
              Estimated Gas: <Text>{quote?.estimatedGas}</Text>
            </Text>
            <PriceSwap />
          </div>
        )}
        
      <div style={{ display:"flex", justifyContent:"space-between", padding:"5px 10px"}}>
      <label htmlFor="">Slippage</label>
      <input type="range" min="0" onChange={changeSlippage} value={newslippage} max="50"  />
        <input type="number" onChange={changeSlippage} value={newslippage} max="50" min="0" name="" placeholder="slippage" id="" />
      </div>
        <Button
          type="primary"
          size="large"
          style={{
            width: "100%",
            marginTop: "15px",
            borderRadius: "0.6rem",
            height: "50px",
          }}
          onClick={() => trySwap(currentTrade)}
          disabled={!ButtonState.isActive}
        >
          {ButtonState.text}
        </Button>
      </Card>
      <Modal
        title="Select a token"
        visible={isFromModalActive}
        onCancel={() => setFromModalActive(false)}
        bodyStyle={{ padding: 0 }}
        width="450px"
        footer={null}
      >
        <InchModal
          open={isFromModalActive}
          onClose={() => setFromModalActive(false)}
          setToken={setFromToken}
          tokenList={tokenList}
        />
      </Modal>
      <Modal
        title="Select a token"
        visible={isToModalActive}
        onCancel={() => setToModalActive(false)}
        bodyStyle={{ padding: 0 }}
        width="450px"
        footer={null}
      >
        <InchModal
          open={isToModalActive}
          onClose={() => setToModalActive(false)}
          setToken={setToToken}
          tokenList={tokendata}
        />
      </Modal>
    </>
  );
}

export default InchDexCustom;

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>
);
1 Like

nice
btw is that the complete code?
and another question can i also build a uniswap clone by only using vanilla js?

Brilliant help. Thanks. I have the same issue :+1:

1 Like

Bummer, tried adjusting slippage as above to 12 & 15 but still get this - any further thoughts?

more detail:

Ta

Answer to my question was to raise slippage to 20

1 Like

hello do you have online demo of your dex?
i would like to see how it works when you select a token

hello
I am using now the ethereum boilerplate and working on dex.
Is it possible to achieve as i am still stuck how to achieve what i want to happen.
My coin is not showing on the list of BSC token list, the only way to show it is by importing it. The question are how can i make may own token display as a default on select token and when user click the select token it will display on the list.
pls. see screenshot
select toekn

do you also have plan how to add custom token via contract address?

1 Like

hi thank for your time giving me some idea how to implement what i need
i am back working on my dex project and already read all your rmesage and idea
I am checking it 1 by 1 all the info you provide and where i can start first to add a custom on my dex that is not listed from api. Where did you get that import link what if i will use bep20 token. How can import that?

1 Like

there isn’t a difference between ERC20 and BEP20 on how you write the code

anyone know what should i do to achieve what i want for my dex?
like steps, resources what section on ivan academy tutorial i need to learn?
hope someone can give me some idea

hi
do you have github file of your custom dex?
i try to follow it but i got some issue

can you help me?
to add my token to ethereum bolierplate?

This code is outdated and can’t be added to the current boilerplate.

I’ll work on the “Custom Add” field but so far:

  1. Added Balance Field - From/To
  2. You can click on the Balance to automatically fill the From Field
  3. Slippage with a nice Warning for High Slippage
  4. Quick Switch between Tokens
  5. Estimated Tokens received as per the new Slippage

    The only thing that is missing is the actual Custom Token field - currently I hardcoded custom tokens in top of the list.
    – VIDEO - https://vimeo.com/676325346
1 Like

I’ve done the same thing in you’ve done in your video without any issues. Slippage changer, custom token, etc…

My only issue, when I try to add custom fees, the whole dapp freez!!

I have noticed your slippage changer input range steps is set to “0.5”. However, Moralis minimum slippage is “1”!