Noted. Thank you Zsolt!
Thanks Zsoft for the course. Iām an amateur programing and I learned a lot because you give me more knowledge and tools to continue working for my goal.
Here is my repository
https://github.com/camarosan/coin-exchange
and the webpage
https://camarosan.github.io/coin-exchange/
I added another statistics and you can update them.
Tested other stylish
There is a input text for a bailout in balance I used hash function with sha256 only for fun the password is Carlos RodrĆguez and the helicopter of my central bank will bring you more balance)
I am currently improving the react app but stumbled upon on a problem.
I have added an icon to the show/hide balance button, when I click the button the icon does not change. I have googled the problem but could not find solution.
export default function AccountBalance(props) {
const buttonClass = 'btn ' + (props.showBalance ? 'btn-warning' : 'btn-info');
const buttonText = props.showBalance ? ' Hide Balance' : ' Show Balance';
const buttonIcon = props.showBalance ? 'fas fa-eye-slash' : 'fas fa-eye';
return (
<Section>
<BalanceToggleButton
className={buttonClass}
onClick={props.handleBalanceVisibility}>
<i className={buttonIcon}></i>
{buttonText}
</BalanceToggleButton>
</Section>
);
};
here is my gitHub repo:
https://github.com/mjwatson10/coin-exchange
for some reason I am having some issues deploying the folder with npm.
any assistance would be greatly appreciated
Iād suggest restarting the whole git-github repository creation in a new folder and copying your source code over. Then check every character, space, comma etc. if they are at their correct places.
https://peacanduck.github.io/coin-exchange/
Added MetaMask so far, going to turn this into a working crypto interface
https://github.com/Uy4n/CoinExchange
Here is my extended project
I was held up a few days by a āhigh severity vulnerabilityā. It turns out it wasnāt so severe, itās just that the automatic audit saw something wrong as potentially very harmful. I didnāt, and still donāt, know enough to know better, so I waited for a fix before continuing.
I knew i wanted to implement a historical price chart, showing the prices of different cryptocurrencies over time. After that I did some styling before carrying on with a few small features. Really the possibilities were endless, so I had to draw the line somewhere otherwise Iād never move onto another project/course!
I could also just copy Uniswapās source code like many other production-ready projects have done
Finally I added some hyperlinks. I tried to make āhomeā icon clickable to go to home, but it turned out to be a bit fiddly. I could do it, but it would probably require code rewiring/restructuring.
Comparing this work with projects Iāve attempted directly involving the blockchain: working with React, I can experiment and make mistakes without having anything permanent on the blockchain. I know that I can use a testnet blockchain, but it still has that feeling of permanence to me; not allowing me to experiment unless I attach a āself-destruct contractā button to every dapp (decentralized app) I develop.
Anyway, Iām much more confident in my ability to code after this. Iād say that was the goal, so goal achieved!
Here are some of the resources I used:
https://api.coinpaprika.com/ (of course)
https://www.youtube.com/watch?v=3m-3qnEXIUk (VERY helpful)
If you want to add even more functionality, check out this resource that I didnāt get to:
https://www.freecodecamp.org/news/how-to-build-historical-price-charts-with-d3-js-72214aaf6ba3/
Keep up the good work mate.
Hi @Malik,
would you help me debug this code? I am trying to loop through a public array and push data to a new array in javascript.
async loop
getCandidates = async () => {
count = 0;
for(count = 0; count < length; count++) {
await voteApp.methods.candidates(count).call().then(function(res){
candsNames.push(res.name);
candsIds.push(count);
console.log(candsNames[1]);
console.log(candsIds[0]);
$("#id_out").text(res.votes);
$("#name_out").text(web3.utils.toAscii(res.name));
})
}
$("#print").text(candsNames + candsIds);
}
Hi @Bhujanga,
Can you be more specific on what the issue is. Extra details like what strategies did you try to solve it and whether you tried console logging it to pin point the issue
Thanks
Hi @Malik,
yes, I will try my best.
I am working on getting data from a struct array into a new arrays in main.js. I tried different solutions.
so far these two seem the most promising to me: (no errors thrown in console)
latest Try
console log running is printed to console
As soon as i wrap await function call into a loop it will not return callbackā¦
async function getCands(){
console.log("running");
//for (let i = 0; i < length; i++) WRAPPING INTO A FOR LOOP LIKE THIS WILL NOT WORK :(
await voteApp.methods.candidates(1).call().then(function(res){
$("#id_out").text(1);
$("#name_out").text(web3.utils.toAscii(res.name));
})
}
async try 1
getCandidates = async () => {
count = 0;
for(count = 0; count < length; count++) {
await voteApp.methods.candidates(count).call().then(function(res){ //the call does not seem to succeed
candsNames.push(res.name); //should push res.name to candsName array
candsIds.push(count); //should push cound to candsIds array
console.log(candsNames[1]); //none of the logs are executed.
console.log(candsIds[0]);
$("#id_out").text(count); //no output is created
$("#name_out").text(web3.utils.toAscii(res.name));
})
}
$("#print").text(candsNames + candsIds);
}
async try 2
async function getCandidates() {
const len = length;
for (let count = 0; count < len; count++) {
await voteApp.methods.candidates(count).call().then(function(res){
candsNames.push(res.name);
candsIds.push(count);
console.log(candsNames[1]);
console.log(candsIds[0]);
$("#id_out").text(res.votes);
$("#name_out").text(web3.utils.toAscii(res.name));
console.log(count);
})
}
$("#print").text(candsNames + candsIds);
}
}
Here is my complete main.js so far. I tried to console.log the counter of the for loop before the async function call (await), and at the end, but nothing.
I also did try to use a while loop, but without success so far.
main.js
var web3 = new Web3(Web3.givenProvider);
var voteApp;
var candsNames = [];
var candsIds = [];
var length;
$(document).ready(function() {
window.ethereum.enable().then(function(accounts){
voteApp = new web3.eth.Contract(window.abi, "0xd2D19f51E12ab8aEC9D22530Bf4644Bc5C9Da8Af", {from: accounts[0]});
getLength();
getCandidates();
});
$("#castVote_button").click(castVote);
});
function castVote(){
let voteID = $("#id_in").val();
voteApp.methods.vote(voteID).send({value: web3.utils.toWei("1", "ether")}) //send will send data to function createPerson
.on("transactionHash", function(hash){ //event listener that listens for transactionHash
console.log("tx hash");
})
.on("confirmation", function(confirmationNumber, receipt){ //listener for confirmationNumber only works on real blockchain as local will not confirm for real
console.log("conf");
})
.on("receipt", function(receipt){
console.log(receipt);
})
}
async function getCandidates() {
const len = length;
for (let count = 0; count < len; count++) {
await voteApp.methods.candidates(count).call().then(function(res){
candsNames.push(res.name);
candsIds.push(count);
console.log(candsNames[1]);
console.log(candsIds[0]);
$("#id_out").text(res.votes);
$("#name_out").text(web3.utils.toAscii(res.name));
console.log(count);
})
}
$("#print").text(candsNames + candsIds);
}
function getLength(){
voteApp.methods.candLength().call().then(function(res){
length = res;
console.log(length);
})
}
Voting.sol
pragma solidity >=0.6.0 <0.8.0;
pragma experimental ABIEncoderV2;
contract Voting{
struct Voter{
address voterAddress;
uint vote; //index of candidate voted for
bool didVote; //false until voter did vote
//voter can only vote when weight is >= 1!
uint weight; //increases when someone delegates his/her vote to this voter or voteMaster approves voter!
address delegate; //address that gets delegated with the vote
}
struct Candidate{
bytes32 name; //name of candidate
uint votes; //keeps track of votes given to this candidate
}
address public voteMaster; //voteMaster is the address approving voterAddress
mapping (address => Voter) public voters; //connects address to Voter structs
Candidate[] public candidates; //stores all candidates input by the voteMaster (deployer) in the constructor
constructor(bytes32[] memory candidateNames) public {
voteMaster = msg.sender;
voters[voteMaster].weight = 1;
for (uint i = 0; i < candidateNames.length; i++){ //pushes all candidate names of candidateName[] (from constructor input) to candidates[] (state array) and sets votes to 0
candidates.push(Candidate({
name: candidateNames[i],
votes: 0
}));
}
}
//gets length for candidate array
function candLength() public view returns(uint nrOfCandidates_){
return nrOfCandidates_ = candidates.length;
}
//Voters validation function, only voteMaster(contrat owner) can execute
function approveVoter(address voter) public {
require(msg.sender == voteMaster, "Only voteMaster can access this function!");
require(!voters[voter].didVote, "Voter already voted!");
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
function vote(uint candidate) public {
Voter storage sender = voters[msg.sender]; //creates Voter variable and sets it to voters[msg.sender]
require(!sender.didVote, "You already did vote!"); //checks if msg.sender did already vote
require(sender.weight > 0, "You are not approved as voter!");
sender.didVote = true;
sender.vote = candidate;
candidates[candidate].votes += sender.weight;
}
function delegateVote(address to) public {
Voter storage sender = voters[msg.sender]; //creates Voter variable sender for msg.sender to have cleaner code for require statement!
require(!sender.didVote, "You cannot delegate your vote because you already voted!");
require(to != msg.sender, "You cannot delegate your vote to yourself!");
require(sender.weight > 0, "You are not approved as voter and can only delegate once you are!");
while(voters[to].delegate != address(0)){ //as long as voters to delegate is not equal to zero address, (in case to also delegates his/her vote),
to = voters[to].delegate; // set to-address equal to voters to delegate, somehow this logic makes me crazy, haha.
require(to != msg.sender, "Found loop in delegation!!");
}
sender.didVote = true; //set senders vote status to true;
sender.delegate = to; //set senders delegate to "to" address
Voter storage delegate_ = voters[to]; //creates Voter variable for delegate to help ourselves in the if statements! makes a cleaner code than to write voters[to] all the time
if(delegate_.didVote){ //check if delegate already didVote, if yes:
candidates[delegate_.vote].votes += sender.weight; //Ok this is tricky. If delegate already did vote, then we add the weight of the sender(that delegate his vote to the delegate) instantly to the candidate that the delegate voted for!
}
else { //if delegate did not vote yet we:
delegate_.weight += sender.weight; //add senders weight to delegates weight.
}
}
function electionWinner() public view returns(uint electionWinner_){ //will return the id of the candidate with the most votes!
uint VotesCount = 0; //to store votes
for (uint p = 0; p < candidates.length; p++) { //loops through all candidates
if (candidates[p].votes > VotesCount) { //and checks if the candidates votes are higher than the votesCount
VotesCount = candidates[p].votes; //If so, then sets the VotesCount equal to the candidates votes
electionWinner_ = p; //and returns candidate ID as electionWinner_
}
}
}
function theWinnerIs() public view returns(bytes32 winnerName_){ //returns name of the winner
return winnerName_ = candidates[electionWinner()].name; //sets winnerName_ to result of [electionWinner()].name. nice and nested functionality here, haha.
}
}
Thanks a lot for looking into this
I am searching forums since days now and canāt make it work
Looking at your code, I believe it is an issue regarding multiple promises.
When you want to do a loop for async calls you need to resolve all of them to get the value. Instead of using a then
to get the callback, you can assign a value and then use it later .
For example -
async function processArray(array) {
// map array to promises
const promises = array.map(delayedLog);
// wait until all promises are resolved
await Promise.all(promises);
console.log('Done!');
}
You can check out references here - https://medium.com/@lavrton/javascript-loops-how-to-handle-async-await-6252dd3c795
Or you could research about loop async await syntaxes and how to use Promise.all for many external API calls.
Unfortunately I cannot write the code for you as this is a very specific case, feel free to experiment with this direction and let me know.
Hope this helps.
UPDATE:
@Malik:
Big celebrations over here
I managed!! This is the code to get all entries of a struct array from a smart contract. This is how one can loop an async function:
Note: candsNames is an array declared in the beginning of the contract.
async function getAllCands() {
const candsLength = await voteApp.methods.candLength().call(); // sets candsLenght by calling getter function to get array length, needs AWAIT!
for (let i = 0; i < candsLength; i++){ //loops for length of array
candsNames.push( //pushes result to candsNames
await voteApp.methods.candidates(i).call().then(result => { //calls the public candidates struct array with await
return [result[0]]; //returns index 0 of candidates struct array entry[i]
})
)
}
console.log(candsNames);
}
Thank you for taking time to look into this. I will keep experimenting!
Hey Guys, iām trying to prevent the app from allowing the user to buy crypto despite not having enough money in the account balance and Iām not sure what the next step is. My code below is in the Coin.jsx file.
import React from 'react';
import PropTypes from "prop-types";
import styled from 'styled-components'
const Td = styled.td`
border: 1px solid #cccccc;
width: 16vw;
`;
const TdControl = styled(Td)`
width: 36vw;
`;
const TdName = styled(Td)`
width: 20vw
`;
const Button = styled.button`
border-radius: 3px;
margin: 0.5em 1em;
`;
export default function Coin(props) {
const handleRefresh = (event) => {
event.preventDefault();
props.handleRefresh(props.tickerId);
}
const handleBuy = (event) => {
event.preventDefault();
if(props.price <= props.balance){
props.handleTransaction( true, props.tickerId );
}
}
const handleSell = (event) => {
event.preventDefault();
if(props.balance > 0){
props.handleTransaction( false, props.tickerId );
}
}
return(
<tr>
<TdName>{props.name}</TdName>
<Td>{props.ticker}</Td>
<Td>${props.price}</Td>
<Td>{props.showBalance ? props.balance : "-"} </Td>
<TdControl>
<form action="#" method ="POST">
<Button className = "btn btn-info" onClick= { handleRefresh } >REFRESH</Button>
<Button className = "btn btn-success" onClick= { handleBuy } >BUY</Button>
<Button className = "btn btn-warning" onClick= { handleSell } >SELL</Button>
</form>
</TdControl>
</tr>
);
}
Coin.propTypes = {
name: PropTypes.string.isRequired,
ticker: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
}`Preformatted text`
Here is my exchange site: https://jelloss.github.io/top-coins-atm/
Here are my project files on Github: https://github.com/jelloss/top-coins-atm
Great course although it was a bit hard to understand sometimes as a beginner but I get how much you can do with react. Very excited to build web apps/dapps with react. You guys sure helped me a lot to get a really solid base knowledge on react and wanna thank you all you helped this made possible.
Have a nice day!
I now see that there is also another video about styling the web app but I made some changes already by myself. Does anyone know how to go back to a branch or something and undo all the changes?
You can always get back to any of the commits you make on git. So, you can do it without any issues.
got that but now I want to push the changes that I have made but then this error occurs
it says that I need to push the HEAD
state to the name of the remote branch but how do I find the remote branch and then push it to the local branch?
Not sure how you ended up in a detached state, but you can see in the blue area of your prompt in the terminal that you are not on a branch.
If you google the āfatal: you are not currently on a branchā error message, you get this StackOverflow link: https://stackoverflow.com/questions/30471557/git-push-master-fatal-you-are-not-currently-on-a-branch/30471627. If you follow the steps there you can at least restore the state, where you have a local branch and a remote branch. Please note you may need to use the branch name main instead of master on GitHub due to GitHub branch naming changes. Check out your GitHub branch to see if it reads master or main.
In general, I highly recommend investing effort into deeply learning git and github. Check out my video I linked in the course: https://www.youtube.com/watch?v=lXU216xeVWU and follow the steps from start to finish.
Finally got it! only thing is that my helicopter button is a little bit different (slightly bigger and no green color) but Iām really happy it finally updated with the remote branch. Thank you for this great course I learned a lot from it. Have a nice day!