GitHub Discussion

If you have questions regarding the use of GitHub, please post below! :raised_hands:

1 Like

Hello Adam !
I’m creating DEX in this courses and then, I’m looking for the source code of DEX. Do you have github’s link of DEX in this course ?

Hello,
Zsolt mentioned about protecting secrets and left GitHub material about it (https://docs.github.com/en/actions/reference/encrypted-secrets). I read it and much more and still do not know how I suppose to get my secrets in main.js. As I understood correctly github secrets are only available in github workflow.

  1. Is it necessary to write file (for example .env) using github workflow and then read it in main.js ?
  2. Is that safe ?
  3. Can somebody give me the other way ?

I mostly use the .env file (which is the dotenv module), then in the gitignore file I add to ignore .env to not upload the secret file to the github repo.

as long as your secret file never get uploaded or shared in internet (incluiding github repo) you should be fine.

Hope it works :nerd_face:

Carlos Z

Thanks for the answer. I was wondering if I can have Github page working as Zsolt showed (name.github.io) without exposing private data. But as I read it is impossible for static page and it is required to have dynamic page with server side included. Is that correct ?

Hi i’ve been having trouble creating a .env file. Whenever I enter require(‘dotenv’).config(); i get an error message on the console saying require not defined

Could you please share your js file? i assume you followed the module installation through npm.

Carlos Z

Hi Carlos,

I’ve only installed npm i dotenv

This is my Java code (dex.js):

require('dotenv').config();

// connect to Moralis server
const serverUrl ="${process.env.SERVER_URL}";
const appId ="${process.env.APP_ID}";
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/LOGOUT AND INITIALISATION */
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.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 = '';
}

async function getStats(){
    const balances = await Moralis.Web3API.account.getTokenBalances({chain: 'eth'});
    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"
                    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);    

/**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 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: 'eth',// The blockchain you want to use (eth/bsc/polygon)
            fromTokenAddress,// The token you want to swap
            toTokenAddress,// The token you want to receive
            amount: Moralis.Units.Token(fromAmount, fromDecimals).toString(),          
        });

        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: ${quote.estimatedGas}
        </p>
        `;

    } catch(e) {
        document.querySelector('.js-quote-container').innerHTML = `
        <p class="error"> The conversion didn't succed!</p>
        `;
    }
}


async function formCancelled(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', formCancelled);

/** 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 <=50)
             .map(token => token.symbol);
 }

 async function getTickerData(tickerList){
     const tokens = await Moralis.Plugins.oneInch.getSupportedTokens({
        chain: 'eth',// The blockchain you want to use (eth/bsc/polygon)   
    });
     const tokenList = Object.values(tokens.tokens);

     return tokenList.filter(token => tickerList.includes(token.symbol));
 }

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;
}


 getTop10Tokens()
 .then(getTickerData)
 .then(renderTokenDropdown);

Here is the package json:

{
  "dependencies": {
    "dotenv": "^16.0.0"
  }
}

Hi Carlos,

I’ve only installed npm i dotenv

This is my Java code (dex.js):

require('dotenv').config();

// connect to Moralis server
const serverUrl ="${process.env.SERVER_URL}";
const appId ="${process.env.APP_ID}";
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/LOGOUT AND INITIALISATION */
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.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 = '';
}

async function getStats(){
    const balances = await Moralis.Web3API.account.getTokenBalances({chain: 'eth'});
    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"
                    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);    

/**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 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: 'eth',// The blockchain you want to use (eth/bsc/polygon)
            fromTokenAddress,// The token you want to swap
            toTokenAddress,// The token you want to receive
            amount: Moralis.Units.Token(fromAmount, fromDecimals).toString(),          
        });

        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: ${quote.estimatedGas}
        </p>
        `;

    } catch(e) {
        document.querySelector('.js-quote-container').innerHTML = `
        <p class="error"> The conversion didn't succed!</p>
        `;
    }
}


async function formCancelled(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', formCancelled);

/** 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 <=50)
             .map(token => token.symbol);
 }

 async function getTickerData(tickerList){
     const tokens = await Moralis.Plugins.oneInch.getSupportedTokens({
        chain: 'eth',// The blockchain you want to use (eth/bsc/polygon)   
    });
     const tokenList = Object.values(tokens.tokens);

     return tokenList.filter(token => tickerList.includes(token.symbol));
 }

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;
}


 getTop10Tokens()
 .then(getTickerData)
 .then(renderTokenDropdown);

Here is my package JSON:

{
  "dependencies": {
    "dotenv": "^16.0.0"
  }
}```

i think the problem might be that you are using the live server app from visual studio to create a webserver for the app, the problem is that all installed modules on nodejs like dotenv will not be loaded by the live server app.

That way, you need to change to a webserver that is executed by node and that way you will have access to all the modules you installed on nodejs.

Here are some links that could help you get a better understanding on it, simple way i can advice is to use the http module.

Hope this helps.

Carlos Z