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>
);
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
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
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
do you also have plan how to add custom token via contract address?
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?
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:
- Added Balance Field - From/To
- You can click on the Balance to automatically fill the From Field
- Slippage with a nice Warning for High Slippage
- Quick Switch between Tokens
- 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
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”!