Hi, I am on the Asynchronous Programming part API. Using different APIs. Also from different computers. But none of them works for me. Can you help me? I have watched the videos but I don’t know if I am doing something wrong. Thanks
Hello guys, I’m building a DEX in Javascript course and I’m getting error:
Uncaught TypeError: Cannot read properties of null (reading ‘addEventListener’)
at dex.js:86:5
Plus if I want to get top 10 tokens, it is pending… It doesn’t give me anything.
Could you please assist me with issue?
Thank you. Martina
Can you please share your dex.js
file in the following way?
Carlos Z
I have continued, but still showing me errors like this, plus I can’t somehow get top 10 tokens or 50.
If I log in with metamask, it is showing me array:0, even if I change it for ‘eth’, so basically if it is 0, I can’t see swap buttons etc…
error1:
Refused to apply style from ‘http://127.0.0.1:5500/#styledex.css’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type, and strict MIME checking is enabled.
error2:
Failed to load resource: the server responded with a status of 404 (Not Found)
code:
// connect to Moralis server
const serverUrl = "https://gputqiwoeam8.usemoralis.com:2053/server";
const appId = "Gc8VjQmyuCv29buPmkjWr0CJPmZoqoVgQEiIY0Fs";
Moralis.start({ serverUrl, appId });
Moralis
.initPlugins()
.then(() => console.log('Plugins has been initialized'));
const $tokenBalanceTBody = document.querySelector('.js-token-balances');
const $selectedToken = document.querySelector('.js-from-token');
const $amountInput = document.querySelector('.js-from-amount');
//converting from Wei using custom function
const tokenValue = (value, decimals) =>
(decimals ? value / Math.pow(10, decimals) : value);
// add from here down
async function login() {
let user = Moralis.User.current();
if (!user) {
user = await Moralis.authenticate();
}
console.log("logged in user:", user);
getStats();
}
async function initSwapForm(event) {
event.preventDefault();
$selectedToken.innerText = event.target.dataset.symbol;
$selectedToken.dataset.address = event.target.dataset.address;
$selectedToken.dataset.decimals = event.target.dataset.decimals;
$selectedToken.dataset.max = event.target.dataset.max;
$amountInput.removeAttribute('disabled');
$amountInput = '';
document.querySelector('.js-submit').removeAttribute('disabled');
document.querySelector('.js-cancel').removeAttribute('disabled');
document.querySelector('.js-quote-container').innerHTML = '';
}
async function getStats(){
const balances = await Moralis.Web3API.account.getTokenBalances({chain: 'polygon'});
console.log(balances);
$tokenBalanceTBody.innerHTML = balances.map( (token, index) => `
<tr>
<td>${index+1}</td>
<td>${token.symbol}</td>
<td>${tokenValue(token.balance, token.decimals)}</td>
<td>
<button
class="js-swap"
data-address="${token.token_address}"
data-symbol="${token.symbol}"
data-decimals="${token.decimals}"
data-max="${tokenValue(token.balance, token.decimals)}"
>
Swap
</button>
</td>
</tr>
`).join('');
for(let $btn of $tokenBalanceTBody.querySelectorAll('.js-swap')) {
$btn.addEventListener('click', initSwapForm);}
}
async function buyCrypto() {
Moralis.Plugins.fiat.buy();
}
async function logOut() {
await Moralis.User.logOut();
console.log("logged out");
}
document.querySelector("#btn-login").addEventListener('click', login);
document.getElementById("btn-buy-crypto").addEventListener('click', buyCrypto);
document.getElementById("btn-logout").addEventListener('click', logOut);
async function getTop10Tokens() {
const response = await fetch('https://api.coinpaprika.com/v1/coins');
const tokens = await response.json();
return tokens
.filter(token => token.rank >= 1 && token.rank <=30)
.map(token => token.symbol);
}
async function getTickerData(tickerList) {
const response = await fetch('https://api.1inch.exchange/v3.0/56/tokens');
const tokens = await response.json();
const tokenList = Object.values(tokens.tokens);
return tokenList.filter(token => tickerList.includes(token.symbol));
}
function renderDropdown(tokens) {
const options = tokens.map(token => `
<option value="${token.address}-${token.decimals}">
${token.name}
</option>
`).join('');
document.querySelector('[name=to-token]').innerHTML = options;
}
getTop10Tokens()
.then(getTickerData)
.then(renderDropdown);
I am doing the login part of DEX with metamask. When I run the code, Below one is showing.
dex.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ali Swap</title>
</head>
<body>
<button id="btn-login">Moralis Login</button>
<button id="btn-logout">Logout</button>
<!-- Moralis SDK code -->
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
<script src="https://unpkg.com/moralis/dist/moralis.js"></script>
<script src="./dex.js"></script>
</body>
</html>
dex.js
const serverUrl = "https://crixzoshpewy.usemoralis.com:2053/server";
const appId = "KxHpYcmCSmieEL6vUl4C4vvdI9su0aSMciz6NmBg";
Moralis.start({ serverUrl, appId });
async function login() {
let user = Moralis.User.current();
if (!user) {
user = await Moralis.authenticate();
}
console.log("logged in user:", user);
}
async function logOut() {
await Moralis.User.logOut();
console.log("logged out");
}
document.querySelector("#btn-login").addEventListener('click', login);
document.querySelector("#btn-logout").addEventListener('click', logOut);
async function getTop10Tokens(){
try{
let response = await fetch('https://api.coinpaprika.com/v1/coins');
let tokens = await response.json();
listItems = tokens.filter(x => x.rank > 0 && x.rank <=10).map(x => x.symbol);
return listItems;
//document.body.innerHTML = `<ol>${listItems.join('')}</ol>`
} catch(e){
console.log(`Error: ${e}`)
}
}
async function getTickerAddress(tickerList){
try{
let response = await fetch('https://api.1inch.exchange/v3.0/137/tokens');
let tokens = await response.json();
let tokenList = Object.values(tokens.tokens);
return tokenList.filter(x => tickerList.includes(x.symbol));
}catch(e){
console.log(`Error : ${e}`);}
}
Can someone help me to resolve this problem?
I have just copy/paste your code, run it with live server from visual code and it does work well from my side, i was able to sign with my account too.
You might want to try to run it again, let me know if it works.
Carlos Z
You should not be able to go into that URL, your server is protected from that kind of requests, what you should do is to open you index.html
with the visual code live server. Then it should work properly like my image
Carlos Z
Still am getting the same error as shown in the my first post
Any help would be appreciated
Not sure why is not working for you, your code does work perfectly from my side, what are you using has web server to open the project on the browser? live server or something else?
Carlos Z
Does your computer have internet? Those errors are show when your browser or computer is not capable to connect with moralis, and it might be not only moralis, thats why i ask if there is any internet issue or something, the connection request to moralis has timed out.
Carlos Z
I tried with different network. It worked perfectly fine. Thanks.
Hi @thecil,
Can u please look at the issue and let me know,
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ali Swap</title>
</head>
<body>
<button id="btn-login">Moralis Login</button>
<button id="buy-crypto">Buy Crypto</button>
<button id="btn-logout">Logout</button>
<h1>Token Balance</h1>
<table>
<thead>
<tr>
<th>#</th>
<th>Symbol</th>
<th>Amount</th>
<th>Action</th>
</tr>
</thead>
<tbody class=".js-token-balance"></tbody>
</table>
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
<script src="https://unpkg.com/moralis/dist/moralis.js"></script>
<script src="./dex.js"></script>
</body>
</html>
js
const serverUrl = "https://crixzoshpewy.usemoralis.com:2053/server";
const appId = "KxHpYcmCSmieEL6vUl4C4vvdI9su0aSMciz6NmBg";
Moralis.start({ serverUrl, appId });
Moralis.initPlugins().then(() =>console.log('plugins initialized'));
const $tokenBalanceTbody = document.querySelector('.js-token-balance');
async function login() {
let user = Moralis.User.current();
if (!user) {
user = await Moralis.authenticate({
signingMessage: "Log in using Moralis",
})
.then(function (user) {
console.log("logged in user:", user);
console.log(user.get("ethAddress"));
})
.catch(function (error) {
console.log(error);
});
}
getStat();
}
async function getStat(){
const balances = await Moralis.Web3API.account.getTokenBalances({chain: 'polygon'});
console.log(balances);
$tokenBalanceTbody.innerHTML = balances.map((token, index) => `
<tr>
<td>${index + 1}</td>
<td>${token.symbol}</td>
<td>${token.balance}</td>
<td>Button</td>
</tr>`).join('');
}
async function buyCrypto() {
Moralis.Plugins.fiat.buy();
}
async function logOut() {
await Moralis.User.logOut();
console.log("logged out");
}
document.querySelector("#btn-login").addEventListener('click', login);
document.querySelector("#buy-crypto").addEventListener('click', buyCrypto);
document.querySelector("#btn-logout").addEventListener('click', logOut);
Thanks
I was wondering if someone could help me out with the swap function part. I tried several different ways to get it working and I keep getting errors. Here are the two main ways I tried with 2 different errors:
I have everything else working but I keep getting errors when I try to implement the swap function for MetaMask.
I’m not worried about the wallet address showing here, It’s a test account.
This is my DEX:
I’m going to list the HTML and CSS first:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Moralis SDK code -->
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
<script src="https://unpkg.com/moralis/dist/moralis.js"></script>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<!-- My CSS -->
<link rel="stylesheet" href="./DEX1.css">
<title>Moo Dex</title>
</head>
<body>
<!-- Top Title -->
<div class="container">
<div class="row">
<div class="col-12 col-md-6">
<h3 style="display: inline-block">Moo Dex</h3>
<h6 style="display: inline-block">Network: Polygon</h6>
</div>
<!-- Top Buttons -->
<div class="col-12 col-md-6 d-flex align-items-center justify-content-md-center">
<button class="btn btn-primary btn-sm" id="btn-login">MetaMask Login</button>
<button class="btn btn-success btn-sm" id="btn-buy-crypto">Buy Crypto</button>
<button class="btn btn-danger btn-sm" id="btn-logout">Logout</button>
</div>
</div>
<!-- Login Label -->
<div class="login-bar" id="login-bar">
<div class="login-address-label" id="login-address-label">User Address: </div>
<div class="login-address" id="login-address"></div>
</div>
<!-- Table Header -->
<table class="table table-dark table-striped">
<thead>
<tr>
<th>#</th>
<th>Symbol</th>
<th>Amount</th>
<th>Action</th>
</tr>
</thead>
<!-- Table Token Balances -->
<tbody class="js-token-balances"></tbody>
</table>
<!-- Amount Field -->
<form action="#" method="POST" class="exchange-form">
<div class="form-row">
<label>
<span class="js-from-token"></span>
Amount:
<input type="text" name="from-amount" class="js-from-amount" disabled />
</label>
<div class="js-amount-error error"></div>
</div>
<br>
<!-- Swapto Dropdown List -->
<div class="form-row">
<label>
Swap to:
<select name="to-token"></select>
</label>
</div>
<br>
<!-- Quote and Cancel Buttons -->
<div class="form-row">
<button type="submit" class="js-submit btn btn-warning btn-md" disabled>Get Quote</button>
<button class="js-cancel btn btn-danger btn-md" disabled>Cancel</button>
</div>
<br>
<!-- Quote Info -->
<div class="quote-box">
<div class="quote-box-label">Quote Info:</div>
<div class="js-quote-container"></div>
</div>
</form>
</div>
<br>
<!-- Approve Quote Button -->
<div class="approve-quote-row">
<button type="submit" class="js-approve btn btn-success btn-md" id="btn-approve" disabled>Approve Quote</button>
</div>
<!-- Bootstrap JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<!-- My Javascript -->
<script src="./DEX1.js"></script>
</body>
</html>
.error {
color: red;
}
body {
background-color: black;
color: whitesmoke;
height: 100%;
}
.btn-sm {
margin: 2px;
padding-top: 3px;
padding-bottom: 3px;
padding-left: 10px;
padding-right: 10px;
}
.btn-md {
margin: 5px;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 20px;
padding-right: 20px;
}
.login-bar {
background-color: rgb(15, 16, 16);
color: rgb(255, 255, 255);
font-weight: bold;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: .75rem;
margin-top: .5rem;
margin-bottom: .5rem;
}
.login-address-label {
font-style: italic;
text-decoration: underline;
}
.js-quote-container {
background-color: rgb(40, 56, 52);
padding: 1rem;
margin-top: 1rem;
margin-left: 1rem;
margin-right: 1rem;
}
.table {
border-bottom:rgb(255, 255, 255);
}
.approve-quote-row {
padding-left: 1rem;
margin-left: 2rem;
}
This is the quote array:
Now if I use the Swap code that is on the Moralis 1inch Plugin Site Section:
This is the error I get when I click the “Approve Quote” button:
This is the JS Code I used and received the error above:
// connect to Moralis server
const serverUrl = "https://omhfs3y6i9tz.usemoralis.com:2053/server";
const appId = "yKfwpciCbpWSXwyVcw4Gq8Hxi46qL9iPo2CPwhuq";
Moralis.start({ serverUrl, appId });
Moralis
.initPlugins()
.then(() => console.log('Plugins have been initialized'));
const $tokenBalanceTBody = document.querySelector('.js-token-balances');
const $selectedToken = document.querySelector('.js-from-token');
const $amountInput = document.querySelector('.js-from-amount');
//** Utilities */
//converting from wei using custom function
const tokenValue = (value, decimals) =>
(decimals ? value / Math.pow(10, decimals) : value);
/** MetaMask Login */
// Login Function
async function login() {
let user = Moralis.User.current()
if (user) {
console.log("User Logged in", user);
console.log(user.get("ethAddress"));
document.getElementById('login-address').innerHTML = user.get('ethAddress');
getStats();
}
if (!user) {
user = await Moralis.authenticate()
.then(function (user) {
console.log("logged in user:", user);
console.log(user.get("ethAddress"));
document.getElementById('login-address').innerHTML = user.get('ethAddress');
getStats();
})
.catch(function (error) {
console.log(error);
});
}
}
// Logout Function
async function logOut() {
await Moralis.User.logOut();
document.getElementById('login-address').innerHTML = 'Logged Out';
console.log("logged out");
}
// Button Click Actions
document.getElementById("btn-login").onclick = login;
document
.getElementById("btn-buy-crypto")
.addEventListener('click', buyCrypto);
document.getElementById("btn-logout").onclick = logOut;
// BuyCrypto Function
async function buyCrypto() {
Moralis.Plugins.fiat.buy();
}
// Swap Form
async function initSwapForm(event) {
event.preventDefault();
$selectedToken.innerText = event.target.dataset.symbol;
$selectedToken.dataset.address = event.target.dataset.address;
$selectedToken.dataset.decimals = event.target.dataset.decimals;
$selectedToken.dataset.max = event.target.dataset.max;
$amountInput.removeAttribute('disabled');
$amountInput.value = '';
document.querySelector('.js-submit').removeAttribute('disabled');
document.querySelector('.js-cancel').removeAttribute('disabled');
document.querySelector('.js-quote-container').innerHTML = '';
document.querySelector('.js-amount-error').innerText = '';
}
//return the metamask wallet balances
async function getStats() {
const balances = await Moralis.Web3API.account.getTokenBalances({chain: 'polygon'});
console.log(balances);
$tokenBalanceTBody.innerHTML = balances.map( (token, index) => `
<tr>
<td>${index + 1}</td>
<td>${token.symbol}</td>
<td>${tokenValue(token.balance, token.decimals)}</td>
<td>
<button
class="js-swap btn btn-success btn-sm"
data-address="${token.token_address}"
data-symbol="${token.symbol}"
data-decimals="${token.decimals}"
data-max="${tokenValue(token.balance, token.decimals)}"
>
Swap
</button>
</td>
</tr>
`).join('');
for (let $btn of $tokenBalanceTBody.querySelectorAll('.js-swap')) {
$btn.addEventListener('click', initSwapForm);
}
}
/** Quote / Swap */
async function formSubmitted(event) {
event.preventDefault();
const fromAmount = Number.parseFloat( $amountInput.value );
const fromMaxValue = Number.parseFloat( $selectedToken.dataset.max );
if ( Number.isNaN(fromAmount) || fromAmount > fromMaxValue ) {
// invalid input
document.querySelector('.js-amount-error').innerText = 'Invalid amount';
return;
} else {
document.querySelector('.js-amount-error').innerText = '';
}
//Submission of the quote request
const fromDecimals = $selectedToken.dataset.decimals;
const fromTokenAddress = $selectedToken.dataset.address;
const [toTokenAddress, toDecimals] = document.querySelector('[name=to-token]').value.split('-');
try {
const quote = await Moralis.Plugins.oneInch.quote({
chain: 'polygon', // The blockchain you want to use (eth/bsc/polygon)
fromTokenAddress: fromTokenAddress, // The token you want to swap
toTokenAddress: toTokenAddress, // The token you want to receive
amount: Moralis.Units.Token(fromAmount, fromDecimals).toString(),
});
console.log(quote);
const toAmount = tokenValue(quote.toTokenAmount, toDecimals);
document.querySelector('.js-quote-container').innerHTML = `
<p>
${fromAmount} ${quote.fromToken.symbol} =
${toAmount} ${quote.toToken.symbol}
</p>
<p>
Gas fee (Wei): ${quote.estimatedGas}
</p>
`;
document.querySelector('.js-approve').removeAttribute('disabled');
} catch(e) {
document.querySelector('.js-quote-container').innerHTML = `
<p class="error">The conversion didn't succedd. </p>
`;
}
}
//activate the approve quote button upon click
document.querySelector('.js-approve').addEventListener('click', swap);
//perform the swap
async function swap() {
const receipt = await Moralis.Plugins.oneInch.swap({
chain: 'bsc', // The blockchain you want to use (eth/bsc/polygon)
fromTokenAddress: fromTokenAddress, // The token you want to swap
toTokenAddress: toTokenAddress, // The token you want to receive
amount: Moralis.Units.Token(fromAmount, fromDecimals).toString(),
fromAddress: Moralis.User.current().get('ethAddress'), // Your wallet address
slippage: 1,
});
console.log(receipt);
}
//cancel the quote form
async function formCanceled(event) {
event.preventDefault();
document.querySelector('.js-submit').setAttribute('disabled', '');
document.querySelector('.js-cancel').setAttribute('disabled', '');
$amountInput.value = '';
$amountInput.setAttribute('disabled', '');
delete $selectedToken.dataset.address;
delete $selectedToken.dataset.decimals;
delete $selectedToken.dataset.max;
document.querySelector('.js-quote-container').innerHTML = '';
document.querySelector('.js-amount-error').innerText = '';
}
document.querySelector('.js-submit').addEventListener('click', formSubmitted);
document.querySelector('.js-cancel').addEventListener('click', formCanceled);
/** To token dropdown preparation */
async function getTop10Tokens() {
const response = await fetch('https://api.coinpaprika.com/v1/coins');
const tokens = await response.json();
return tokens
.filter(token => token.rank >= 1 && token.rank <= 20)
.map(token => token.symbol);
}
//get ticker data from 1inch
async function getTickerData(tickerList) {
const tokens = await Moralis.Plugins.oneInch.getSupportedTokens({
chain: 'polygon', // The blockchain you want to use (eth/bsc/polygon)
});
const tokenList = Object.values(tokens.tokens);
return tokenList.filter(token => tickerList.includes(token.symbol));
}
//return the tokens available in the dropdown list
function renderTokenDropdown(tokens) {
const options = tokens.map(token => `
<option value="${token.address}-${token.decimals}">
${token.name}
</option>
`).join('');
document.querySelector('[name=to-token]').innerHTML = options;
}
//pull the tokens from 1nch
getTop10Tokens()
.then(getTickerData)
.then(renderTokenDropdown);
But then if I include the variables, I get a different error when I click the “Approve Quote” button:
This is the code I used to receive the above error:
//perform the swap
async function swap() {
const fromDecimals = $selectedToken.dataset.decimals;
const fromTokenAddress = $selectedToken.dataset.address;
const [toTokenAddress, toDecimals] = document.querySelector('[name=to-token]').value.split('-');
const fromAmount = Number.parseFloat( $amountInput.value );
const receipt = await Moralis.Plugins.oneInch.swap({
chain: 'polygon', // The blockchain you want to use (eth/bsc/polygon)
fromTokenAddress: fromTokenAddress, // The token you want to swap
toTokenAddress: toTokenAddress, // The token you want to receive
amount: Moralis.Units.Token(fromAmount, fromDecimals).toString(),
fromAddress: Moralis.User.current().get('ethAddress'), // Your wallet address
slippage: 1,
});
console.log(receipt);
}
I also tried to use a second try catch and that didn’t work.
So I am kind of stuck and not sure what to try next…
What am I doing wrong here?
Thank you in advanced for any replies.
hey this is hard to debug from just looking at your code snippets above. have you a link to a github repo or anything
Tricky misspell, you added a dot .
at the start of the class name, therefore when const $tokenBalanceTBody = document.querySelector(".js-token-balances");
is declared, its value is null because you misstyped.
Just remove the dot from the tbody
classname and it should work.
(you can verify that it does contain a value by adding this to the getStat()
function)
console.log(balances, $tokenBalanceTBody)
Carlos Z