Exercise - Extend your Coin Exchange with more functionality

Extend your Coin Exchange with more functionality.

The scope of this exercise depends on you. Some hints:

  • Add more styles based on your imagination
  • Add a helicopter button that adds $1200 to your balance
  • Buy and sell coins
  • Display a graph of prices
  • Display news and other details on a coin upon click
2 Likes

Just wanted to say I really enjoyed this course! Zsolt, I admire your teaching style and look forward to future courses at the academy from you. All the tips, tricks, and extra effort into explaining things so students will understand whatā€™s actually going on at a fundamental level is greatly appreciated! :star_struck:

Will likely add much more later but for now here is my project submission:

  • Added some basic styling and formatting
  • Added a ā€œHelicopter Moneyā€ button

And here is the github pages link. I didnā€™t have a github pages landing page until today. Itā€™s super basic but it will do for now.
https://jermay.github.io/coin-exchange/

Next I will be converting my bootcamp example projects to React! The Coin Parrot CMC clone, Academy Ethscan, and personal implementation of Academy Kitties. :rocket:

2 Likes

Great job, you are the first one who posted a working solution. Even your commit messages are meaningful.

Hopefully, you are now equipped with cutting edge React skills.

1 Like

Hello, this is my github page :smiley:

https://ibourn.github.io/coin-exchange/

and my repo :

https://github.com/ibourn/coin-exchange

(The link launches on 404 cause i implemented router and redirect. The github page url of the page donā€™t match but all is ok just navigate with the menu. (i will search a way to avoid to have 404 on the first page via github-pages)) Solved! :grinning:

As an extra, i used : router, navlink, redirect, useContext. And i tried to make nested routes.
The login function is fake, as thereā€™s no back-end. I just use the hook useContext to simulate this functionality.
You need to login to access : buy, sell and balance, and to go to the profile page.
To refresh the price you have two options : as in the course (the button is called ā€˜lazyā€™) or automatically (the app refresh the prices each 20 seconds).
When thereā€™s a change in the price, it blinks green or red to gain attention.
In the table, if you click a coin name you will get the latest tweets about it.

Iā€™d like to do more, as learn the MERN patternā€¦ or simply to use useParamsā€¦ :thinking:but iā€™ve a project waiting for the bootcamp. (This web app will be a good base).

I really enjoyed this course, the way you make understand the process and all the things around (github, visual code).

When will the next course to go further! :smiley:

2 Likes

On your router issue: use HashRouter (https://reactrouter.com/web/api/HashRouter). The rest of your code stays unchanged, and instead of regular routing, you use a hashmark, and the route is appended after the hash in the URL. This wonā€™t conflict with GitHub pages.

Cool that you added some creativity (green, red animation).

For the login on server side, indeed you can use Express and Mongo; or also Django if you prefer Python. Both are super easy. But then, for the server-side code, youā€™ll need another deployment method, such as Heroku, Azure, AWS, or even Netlify using a special cloud functions implementation.

1 Like

Thanks.
I saw the HashRouter option, but i just add a route for ā€˜/coin-exchange*ā€™ pointing to the same page than ā€˜/ā€™. It works fine.
I will look Express, Mongo, Heroku soon.

Your project looks much better than mine! I was eager to jump into converting my academy kitties project into React. If you also decide to do your kitties project with React youā€™ll find it easier, but also more work as Filipā€™s samples use jquery. React-bootstrap is fun too and Styled Components plays nice with it.

2 Likes

Cool, even better, great job finding a workaround.

1 Like

Thanks you very much @mayjer. Yes i will try to do kitties project with React but at the moment iā€™m trying to finish the coin market cap clone with react with theming, chartsā€¦ Iā€™m a little stuck. I didnā€™t plan on a lot of small details, so Iā€™m going to downgrade the features (I look forward to starting the ETH projects :sweat_smile:).
And yes for react-bootstrap. I should have used it. Using the regular bootstrap requires many trick (for drop downā€¦)

1 Like

Finally, i used regex in paths, itā€™s the better option i found.

1 Like

Iā€™ve another underwhelming submission. I just added the obvious account limit checks. Iā€™d like to learn more about using multiple pages and pop-up dialog boxes.

But like everyone else here so far: I need to get back to work at the BootCamp. I was going to bend the React coin-exchange into a re-do of the Coin Market Cap clone (project 1), but Iā€™ve already slipped the schedule far enough for this detour through React. I will however redo my critter in svg instead of css (I took 2 courses in that lately), and do everything henceforth in React-bootstrap.

This was by far the densest course at the academy. Itā€™s chock-o-block full of tips, tools, references, and cheats. My notes fell behind in the API section and Iā€™ve still a ton of documentation reading to catch up on. Hopefully that will round out in the coming months (at BootCamp).

I would also like to take your GitHub course. Iā€™m a refugee from ClearCase and still not settled in the culture.

And if youā€™ve a NodeJS course Iā€™d love to take it.

And React 201 and 301 would be welcome. Itā€™s plain you only covered the core third of the material in this course. Youā€™ve obviously 2 more courses worth to say that Iā€™d like to hear someday.

2 Likes

You would be surprised how often this core is solely used in companies. There are of course topics like Redux, Redux Saga, React Router, advanced React patterns etc., but often times the core is what gets you into companies or gets you started with the technology. Often times people without relevant experience start fiddling with advanced stuff (201/301), and then a senior engineer comes along and asks the engineer to simplify and use just the basics for the sake of writing maintainable code.

However, once the basics are rock solid, moving forward is inevitable.

2 Likes

Iā€™m not finished with it yet, and will add to it while Im learning and taking my other coursesā€¦ I love these courses so much, that I plan on always referring back to them and reposting as I improve! Thanks Zsolt!

https://superstar8.github.io/CryptoCoin-Exchange/

2 Likes

Here is my project!
https://timmy-bergkvist.github.io/coin-exchange/

This is the first time I tried React and I really liked it. Thanks for a great course! :+1:

4 Likes

There is not much left from the implementation, good job so far!

When it is hard to read the contrast between a color and a background, check out https://contrast-finder.tanaguru.com/ and make sure contrast is at least 3.5:1. If you donā€™t want to read the CSS or the developer tools on which color you use, you can also use the Chrome extension Color Pick Eyedropper.

2 Likes

Great job, congratulations on following the course to the end!

2 Likes

hey Everyone, im trying to create a Swap UI based on the app we created together, im stuck however, how can i get some help examining my code and bugs etc?

1 Like

Hello @Bdos87, hope you are great.

You can use the ā€œPreformatted Textā€ Button to encapsulate any kind of code you want to show.


function formatText(){

let words = ā€œIā€™m a preformatted Text box, Please use me wisely!ā€

}

prefromatted_text-animated

Carlos Z.

import logo from './logo.svg';
import './App.css';
import Swap from './swap';
import Transact from './transaction'; 
import React, { Component } from 'react'
import WalletBalance from './walletbalance';
import Balance from './balance'
import styled from 'styled-components'; 

const Section = styled.section`
    font-size: 12px;
    border: 1px solid black;
    text-align: center;
    padding: 1rem 0 1rem ;
    width: 35vh;
    font-color: black;
`;
   


 export default class App extends Component {
   constructor (props){
     super(props);
     this.currencies = ["ETH","DAI","MKR","LINK","KNC","LEND","WETH"];

     this.state={
    
     confirm: false,
     swap: false,
     amount: "",
     converted: "",
     base: "ETH",
     other: "DAI",
     blockId: "",
     timeStamp:"",
     price: "",
     /*liquidityPool: "",*/

     wallets: [
      {ticker:"ETH", total: 3000 ,},
      {ticker:"WETH", total:0,},
      {ticker:"LEND", total:150000,},
      {ticker:"LINK", total:10000,},
      {ticker:"KNC", total: 0,},
      {ticker:"MKR", total:500,},
      {ticker:"DAI", total: 500000,} ] 




     }

     };
       


  
     render() {
      /*const timestamp = date.now();
      const txId = ""; */
      
      
    

       return (
       <div>
        <div className="App">
        
           <button className="register">SIGN UP</button>
         
           <button className="enter">LOGIN</button>

           <header>
          
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />

          <p>
          DRaU
          </p>
              <Swap amount={this.state.amount} other={this.state.other} converted={this.state.converted} base={this.state.base} makeSelection={this.makeSelection} changeValue={this.changeValue} calculateSwap={this.calculateSwap}
              swap={this.state.swap} confirm={this.state.confirm} makeTransaction={this.makeTransaction} resetSwap={this.resetSwap} resetTransaction={this.resetTransaction} showTranId={this.showTranId}/>
                 <br></br>  
                
                 <h1 className="details"><Transact sold={this.state.amount} bought={this.state.converted} core={this.state.base} alter={this.state.other} confirm={this.state.confirm} swap={this.state.swap} price={this.state.price}/></h1>
                 
                 </header>   
       
       <Section>
        <table> 
        <thead >
        <Balance account=  {this.state.totalBalance}/> 
        
        </thead>
        <tbody>
        <tr>
        <th>Wallet Balance</th>
        </tr>
        
        {this.state.wallets.map((values) =>
            <WalletBalance ticker={values.ticker} total={values.total} />
            )
            }
         
          </tbody>
        </table>

        </Section>     
        
                </header>
                
                </div>  
                
          
            
          
       
            </div>
         
       )
     }

     makeSelection = (event) => {
      
      this.setState({ 

        [event.target.className]: event.target.value  
  
        }, this.calculateSwap);

    
   }

   changeValue = (event) => {
     this.setState({

      amount: event.target.value,
      converted: "",

     }, this.calculateSwap);
   }

   calculateSwap = () => {
    
     const isValid = parseFloat(this.state.amount);
    if (isNaN(isValid)){
      return ;
    }

    fetch(`https://api.0x.org/swap/v1/quote?buyToken=${this.state.other}&sellToken=${this.state.base}&sellAmount=${this.state.amount}`)
    .then(response => response.json())
    .then( data => {
      
      var dateTime= new Date();
     
      this.setState({
       
       converted: data.price * isValid,
       blockId: data.allowanceTarget,
       timeStamp: dateTime,
       price: data.price,
      /*  liquidityPool: data.sources[1].name */

     });
      

    });
}
 

  makeTransaction = () => {
    const sold= this.state.amount;
    const core = this.state.base;
    const alter=this.state.other; 
    const bought= this.state.converted;
  
    if(isNaN(sold)){
  
     alert("unable to process");
       return false;
     }
  
     else if(isNaN(bought)){
      alert("unable to process");
      return false;
      
     }
    
     else if(core===alter){
      
      alert("unable to process");
      return false;
     
  
     } 
     else if(bought===0){

      alert("unable to process");
      return false;
     }
     else if(bought===""){

      alert("unable to process");
      return false;
     }
     else if(sold===""){

      alert("unable to process");
      return false;
     }
     
     else{
     
      this.setState({
      swap: true,

      
     });
  }
     setTimeout(this.resetSwap, 5000);
       
     }
     

     resetSwap = () => {
     
      this.setState({
           
      swap: false,
      confirm: true,
      

      });
      setTimeout(this.resetTransaction, 7000);
 }  

 resetTransaction = () =>{

  this.setState({
    confirm: false,
    amount: "",
    converted: "",
  }, this.showTranId);

 }
   
showTranId = () => {
  return (
    <>{this.state.timeStamp} {this.state.blockId}</>
  );
}

 calculateBalance = () =>{
const values = this.state.wallets;
const base = this.state.base;
const other = this.state.other;
const amount = this.state.amount;
const converted = this.state.converted;

for (var n=0; n<values.length; n++){ 
 
  let balance =values[n].total;

if ((values[n].ticker === base) && (values[n].total !==0)) {
     balance = values[n].total - amount;

}

else if (values[n].ticker===other){  
   balance = values[n].total + converted;
} 

else{ 
  balance = 0;

}


this.setstate({}) }
  
  

}

 }

Hey Carlos, im having trouble with two things.

1)how do i return a value from a function like i have in the ā€˜showTranIDā€™ function and then insert that into the DOM. ie, return a h1 in my App that holds those values generated from the function. I remember in Jquery we would use $ to refer to an element or use document.getelementbyId. i guess im just struggling how to use the jsx syntax within a function call etc.

  1. (calculateBalance) im having trouble updating the set state array for this.state.wallets with the new wallets.total value. again another syntax or code structuring issue.

i would very much appreciate any assistance in helping me solve these problems. thank you

calculateBalance = () =>{
  const base = this.state.base;
  const amount = this.state.amount;
  const converted = this.state.converted; 
  const other = this.state.other;

  const newWallets = this.state.wallets.map(function({ticker,total}){
   let newTotal=total;

   if (ticker===base) {
    newTotal=newTotal - (amount);
   }
   else if (ticker===other){
    newTotal=newTotal + (converted);
  }
  
   return {
       ticker,
       total: newTotal,
       
   }
  });
  
  this.setState({wallets: newWallets});
  }    

i have tweaked it so its similar to the coin exchange app, but it still cant get it to run and update the balances. i have provided the states as props to the walletBalance component, but still nothing