Sunday, October 31, 2021
Wednesday, October 27, 2021
selenium 3 fill input
form default input value Jone Doe
automate testing fills in chuan shuo
submit button click is automated
#main.py
import os
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
os.environ['PATH'] += r"C:/Users/zchen/PycharmProjects/selenium"
driver = webdriver.Chrome()
driver.get("https://www.w3schools.com/html/html_forms.asp")
driver.implicitly_wait(30)
firstName = driver.find_element(By.ID, 'fname')
lastName = driver.find_element(By.ID, 'lname')
firstName.clear()
firstName.send_keys('chuan')
lastName.clear()
lastName.send_keys('shuo')
submitButton = driver.find_element(By.XPATH, "//input[@type='submit' and @value='Submit']")
submitButton.click()
find submit button
Tuesday, October 26, 2021
selenium 2 conditional wait
when label is 100%, print
#logs
DevTools listening on ws://127.0.0.1:59251/devtools/browser/50b6c55d-da1f-433c-85bf-ca7f40c0543a
progress bar is 100%
#main.py
import os
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
os.environ['PATH'] += r"C:/Users/zchen/PycharmProjects/selenium"
driver = webdriver.Chrome()
driver.get("https://www.w3schools.com/howto/howto_js_progressbar.asp")
driver.implicitly_wait(30)
runButton = driver.find_element(By.XPATH, '//button[text()="Run"]')
runButton.click()
WebDriverWait(driver, 30).until(
EC.text_to_be_present_in_element(
(By.ID, 'prlabel'),
'100%'
)
)
print('progress bar is 100%')
reference:
Monday, October 25, 2021
selenium 1
#terminal
pip install selenium
#chrome browser
chrome://version/
Google Chrome 94.0.4606.81 (Official Build) (64-bit) (cohort: Stable)
go to https://chromedriver.chromium.org/downloads
download current version driver
download win32.zip and extract to C:/Users/zchen/PycharmProjects/selenium
automate click run button on website
#main.py
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
os.environ['PATH'] += r"C:/Users/zchen/PycharmProjects/selenium"
driver = webdriver.Chrome()
driver.get("https://www.w3schools.com/howto/howto_js_progressbar.asp")
driver.implicitly_wait(30)
runButton = driver.find_element(By.XPATH, '//button[text()="Run"]')
runButton.click()
reference:
locate element
Sunday, October 24, 2021
solidity 5 transfer transferFrom
//TokenFram.sol
pragma solidity ^0.5.0;
import "./DappToken.sol";
import "./DaiToken.sol";
contract TokenFarm {
string public name = "Dapp Token Farm";
address public owner;
DappToken public dappToken;
DaiToken public daiToken;
address[] public stakers;
mapping(address => uint) public stakingBalance;
mapping(address => bool) public hasStaked;
mapping(address => bool) public isStaking;
constructor(DappToken _dappToken, DaiToken _daiToken) public {
dappToken = _dappToken;
daiToken = _daiToken;
owner = msg.sender;
}
function stakeTokens(uint _amount) public {
// Require amount greater than 0
require(_amount > 0, "amount cannot be 0");
// Trasnfer Mock Dai tokens to this contract for staking
daiToken.transferFrom(msg.sender, address(this), _amount);
// Update staking balance
stakingBalance[msg.sender] = stakingBalance[msg.sender] + _amount;
// Add user to stakers array *only* if they haven't staked already
if(!hasStaked[msg.sender]) {
stakers.push(msg.sender);
}
// Update staking status
isStaking[msg.sender] = true;
hasStaked[msg.sender] = true;
}
// Unstaking Tokens (Withdraw)
function unstakeTokens() public {
// Fetch staking balance
uint balance = stakingBalance[msg.sender];
// Require amount greater than 0
require(balance > 0, "staking balance cannot be 0");
// Transfer Mock Dai tokens to this contract for staking
daiToken.transfer(msg.sender, balance);
// Reset staking balance
stakingBalance[msg.sender] = 0;
// Update staking status
isStaking[msg.sender] = false;
}
// Issuing Tokens
function issueTokens() public {
// Only owner can call this function
require(msg.sender == owner, "caller must be the owner");
// Issue tokens to all stakers
for (uint i=0; i<stakers.length; i++) {
address recipient = stakers[i];
uint balance = stakingBalance[recipient];
if(balance > 0) {
dappToken.transfer(recipient, balance);
}
}
}
}
-------------------
//DaiToken.sol
pragma solidity ^0.5.0;
contract DaiToken {
string public name = "Mock DAI Token";
string public symbol = "mDAI";
uint256 public totalSupply = 1000000000000000000000000; // 1 million tokens
uint8 public decimals = 18;
event Transfer(
address indexed _from,
address indexed _to,
uint256 _value
);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _value
);
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
constructor() public {
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
}
reference:
Saturday, October 23, 2021
solidity 4 inheritance
get secret from guest
//logs
call to MyContract.getSecret errored: VM error: revert.
revert
The transaction has been reverted to the initial state.
Reason provided by the contract: "must be owner".
Debug the transaction to get more information.
------------------
//MyContract.sol
pragma solidity ^0.6.0;
contract Ownable{
address owner;
constructor() public{
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner, 'must be owner');
_;
}
}
contract MyContract is Ownable{
string secret;
constructor(string memory _secret) public{
secret = _secret;
super;
}
function getSecret() public view onlyOwner returns(string memory){
return secret;
}
}
-----------------------------
//MyContract2.sol
pragma solidity ^0.6.0;
contract Ownable{
address owner;
constructor() public{
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner, 'must be owner');
_;
}
}
contract SecrectVault{
string secrect;
constructor(string memory _secrect) public{
secrect = _secrect;
}
function getSecret() public view returns(string memory){
return secrect;
}
}
contract MyContract is Ownable{
address secrectVault;
constructor(string memory _secrect) public{
SecrectVault _secrectVault = new SecrectVault(_secrect);
secrectVault = address(_secrectVault);
super;
}
function getSecret() public view onlyOwner returns(string memory){
SecrectVault _secrectVault = SecrectVault(secrectVault);
return _secrectVault.getSecret();
}
}
reference:
Thursday, October 21, 2021
solidity 3 hotel booking
select guest account
send ether to owner
//logs
//send 1 ether to hotel
revert
The transaction has been reverted to the initial state.
Reason provided by the contract: "Not enought Ether provided.".
Debug the transaction to get more information.
transact to HotelRoom.(receive) pending ...
//send 2 ether to hotel
[vm] from: 0xAb8...35cb2to: HotelRoom.(receive) 0xd91...39138value: 2000000000000000000 weidata: 0xlogs: 1hash: 0xfec...dc117
transact to HotelRoom.(receive) pending ...
//send 2 ether to hotel again
[vm] from: 0xAb8...35cb2to: HotelRoom.(receive) 0xd91...39138value: 2000000000000000000 weidata: 0xlogs: 0hash: 0x5fa...6ed65
transact to HotelRoom.(receive) errored: VM error: revert.
revert
The transaction has been reverted to the initial state.
Reason provided by the contract: "Currently Occupied".
Debug the transaction to get more information.
-----------------------
//HotelRoom.sol
pragma solidity ^0.6.0;
contract HotelRoom {
enum Statuses {Vacant, Occupied}
Statuses currentStatus;
event Occupy(address _occupant, uint _value);
address payable public owner;
constructor() public {
owner = msg.sender;
currentStatus = Statuses.Vacant;
}
modifier onlyWhileVacant {
require(currentStatus == Statuses.Vacant, "Currently Occupied");
_;
}
modifier costs(uint _amount){
require(msg.value >= _amount, "Not enought Ether provided.");
_;
}
receive() external payable onlyWhileVacant costs(2 ether){
currentStatus = Statuses.Occupied;
owner.transfer(msg.value);
emit Occupy(msg.sender, msg.value);
}
}
reference:
Wednesday, October 20, 2021
Monday, October 18, 2021
solidity 2 nested mapping
add a book
get book based on publisher -> id
//mycontract.sol
pragma solidity ^0.6.0;
contract MyContract {
mapping(address => mapping(uint => Book)) public myBooks;
struct Book{
string title;
string author;
}
function addMyBook(uint _id, string memory _title, string memory _author) public {
myBooks[msg.sender][_id] = Book(_title, _author);
}
}
reference:
Sunday, October 17, 2021
solidity 1
compiler
deploy
//counter.solpragma solidity ^0.6.0;
contract Counter{
uint count;
constructor() public{
count = 1;
}
function getCount() public view returns(uint){
return count;
}
function incrementCount() public{
count = count + 1;
}
}
---------------------------
//easier counter.sol
pragma solidity ^0.6.0;
contract Counter{
uint public count = 1;
function incrementCount() public{
count++;
}
}
reference:
Saturday, October 16, 2021
Friday, October 15, 2021
Thursday, October 14, 2021
Ethereum Programming 21 youtube clone
import React, { Component } from 'react';
import DVideo from '../abis/DVideo.json'
import Navbar from './Navbar'
import Main from './Main'
import Web3 from 'web3';
import './App.css';
//Declare IPFS
const ipfsClient = require('ipfs-http-client')
const ipfs = ipfsClient({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' }) // leaving out the arguments will default to these values
class App extends Component {
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
}
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
await window.ethereum.enable()
}
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
}
else {
window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
}
async loadBlockchainData() {
const web3 = window.web3
// Load account
const accounts = await web3.eth.getAccounts()
console.log(accounts[0])
this.setState({ account: accounts[0] })
// Network ID
const networkId = await web3.eth.net.getId()
const networkData = DVideo.networks[networkId]
if (networkData) {
const dvideo = new web3.eth.Contract(DVideo.abi, networkData.address)
this.setState({ dvideo })
const videosCount = await dvideo.methods.videoCount().call()
this.setState({ videosCount })
// Load videos, sort by newest
for (var i = videosCount; i >= 1; i--) {
const video = await dvideo.methods.videos(i).call()
this.setState({
videos: [...this.state.videos, video]
})
}
//Set latest video with title to view as default
const latest = await dvideo.methods.videos(videosCount).call()
this.setState({
currentHash: latest.hash,
currentTitle: latest.title
})
this.setState({ loading: false })
} else {
window.alert('DVideo contract not deployed to detected network.')
}
}
//Get video
captureFile = event => {
event.preventDefault()
const file = event.target.files[0]
const reader = new window.FileReader()
reader.readAsArrayBuffer(file)
reader.onloadend = () => {
this.setState({ buffer: Buffer(reader.result) })
console.log('buffer', this.state.buffer)
}
}
//Upload video
uploadVideo = title => {
console.log("Submitting file to IPFS...")
//adding file to the IPFS
ipfs.add(this.state.buffer, (error, result) => {
console.log('IPFS result', result)
if (error) {
console.error(error)
return
}
this.setState({ loading: true })
this.state.dvideo.methods.uploadVideo(result[0].hash, title).send({ from: this.state.account }).on('transactionHash', (hash) => {
this.setState({ loading: false })
})
})
}
//Change Video
changeVideo = (hash, title) => {
this.setState({ 'currentHash': hash });
this.setState({ 'currentTitle': title });
}
constructor(props) {
super(props)
this.state = {
buffer: null,
account: '',
dvideo: null,
videos: [],
loading: true,
currentHash: null,
currentTitle: null
}
//Bind functions
this.uploadVideo = this.uploadVideo.bind(this)
this.captureFile = this.captureFile.bind(this)
this.changeVideo = this.changeVideo.bind(this)
}
render() {
return (
<div>
<Navbar
account={this.state.account}
/>
{this.state.loading
? <div id="loader" className="text-center mt-5"><p>Loading...</p></div>
: <Main
captureFile={this.captureFile}
uploadVideo={this.uploadVideo}
currentHash={this.state.currentHash}
currentTitle={this.state.currentTitle}
videos={this.state.videos}
changeVideo={this.changeVideo}
/>
}
</div>
);
}
}
export default App;
--------------------------------
//src/components/main.js
import React, { Component } from 'react';
class Main extends Component {
render() {
return (
<div className="container-fluid text-monospace">
<br></br>
<br></br>
<div className="row">
<div className="col-md-10">
<div className="embed-responsive embed-responsive-16by9" style={{ maxHeight: '768px' }}>
{/* Video... */}
<video
src={`https://ipfs.infura.io/ipfs/${this.props.currentHash}`}
controls
>
</video>
</div>
<h3><b><i>{this.props.currentTitle}</i></b></h3>
</div>
<div className="col-md-2 overflow-auto text-center" style={{ maxHeight: '768px', minWidth: '175px' }}>
<h5><b>Share Video</b></h5>
<form onSubmit={(event) => {
{/* Upload Video...*/ }
event.preventDefault()
const title = this.videoTitle.value
this.props.uploadVideo(title)
}} >
{/* Get Video...*/}
<input type='file' accept=".mp4, .mkv .ogg .wmv" onChange={this.props.captureFile} style={{ width: '250px' }} />
<div className="form-group mr-sm-2">
<input
id="videoTitle"
type="text"
ref={(input) => { this.videoTitle = input }}
className="form-control-sm"
placeholder="Title..."
required />
</div>
<button type="submit" className="btn btn-danger btn-block btn-sm">Upload!</button>
</form>
{/* Map Video...*/}
{/* Return Video...*/}
{this.props.videos.map((video, key) => {
return (
<div className="card mb-4 text-center bg-secondary mx-auto" style={{ width: '175px' }} key={key} >
<div className="card-title bg-dark">
<small className="text-white"><b>{video.title}</b></small>
</div>
<div>
<p onClick={() => this.props.changeVideo(video.hash, video.title)}>
<video
src={`https://ipfs.infura.io/ipfs/${video.hash}`}
style={{ width: '150px' }}
/>
</p>
</div>
</div>
)
})}
</div>
</div>
</div>
);
}
}
export default Main;
---------------------------
//src/contracts/DVideo.sol
pragma solidity ^0.5.0;
contract DVideo {
uint public videoCount = 0;
string public name = "DVideo";
mapping(uint => Video) public videos;
//Create id=>struct mapping
//Create Struct
struct Video{
uint id;
string hash;
string title;
address author;
}
//Create Event
event VideoUploaded(
uint id,
string hash,
string title,
address author
);
constructor() public {
}
function uploadVideo(string memory _videoHash, string memory _title) public {
// Make sure the video hash exists
require(bytes(_videoHash).length > 0);
// Make sure video title exists
require(bytes(_title).length > 0);
// Make sure uploader address exists
require(msg.sender != address(0));
// Increment video id
videoCount++;
// Add video to the contract
videos[videoCount] = Video(videoCount, _videoHash, _title, msg.sender);
// Trigger an event
emit VideoUploaded(videoCount, _videoHash, _title, msg.sender);
}
}
-------------------------
//test/test.js
const DVideo = artifacts.require('./DVideo.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('DVideo', ([deployer, author]) => {
let dvideo
before(async () => {
dvideo = await DVideo.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await dvideo.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await dvideo.name()
assert.equal(name, 'DVideo')
})
})
describe('videos', async () => {
let result, videoCount
const hash = 'QmV8cfu6n4NT5xRr2AHdKxFMTZEJrA44qgrBCr739BN9Wb'
before(async () => {
result = await dvideo.uploadVideo(hash, 'Video title', { from: author })
videoCount = await dvideo.videoCount()
})
//check event
it('creates videos', async () => {
// SUCESS
assert.equal(videoCount, 1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), videoCount.toNumber(), 'id is correct')
assert.equal(event.hash, hash, 'Hash is correct')
assert.equal(event.title, 'Video title', 'title is correct')
assert.equal(event.author, author, 'author is correct')
// FAILURE: Video must have hash
await dvideo.uploadVideo('', 'Video title', { from: author }).should.be.rejected;
// FAILURE: Video must have title
await dvideo.uploadVideo('Video hash', '', { from: author }).should.be.rejected;
})
//check from Struct
it('lists videos', async () => {
const video = await dvideo.videos(videoCount)
assert.equal(video.id.toNumber(), videoCount.toNumber(), 'id is correct')
assert.equal(video.hash, hash, 'Hash is correct')
assert.equal(video.title, 'Video title', 'title is correct')
assert.equal(video.author, author, 'author is correct')
})
})
})
reference:
Wednesday, October 13, 2021
Monday, October 11, 2021
Ethereum Programming 20 collect token after find a match
find a match
confirm transaction
collect token
//src/components/app.js
import React, { Component } from 'react';
import Web3 from 'web3'
import './App.css';
import MemoryToken from '../abis/MemoryToken.json'
import brain from '../brain.png'
const CARD_ARRAY = [
{
name: 'fries',
img: '/images/fries.png'
},
{
name: 'cheeseburger',
img: '/images/cheeseburger.png'
},
{
name: 'ice-cream',
img: '/images/ice-cream.png'
},
{
name: 'pizza',
img: '/images/pizza.png'
},
{
name: 'milkshake',
img: '/images/milkshake.png'
},
{
name: 'hotdog',
img: '/images/hotdog.png'
},
{
name: 'fries',
img: '/images/fries.png'
},
{
name: 'cheeseburger',
img: '/images/cheeseburger.png'
},
{
name: 'ice-cream',
img: '/images/ice-cream.png'
},
{
name: 'pizza',
img: '/images/pizza.png'
},
{
name: 'milkshake',
img: '/images/milkshake.png'
},
{
name: 'hotdog',
img: '/images/hotdog.png'
}
]
class App extends Component {
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
this.setState({ cardArray: CARD_ARRAY.sort(() => 0.5 - Math.random()) })
}
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
await window.ethereum.enable()
}
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
}
else {
window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
}
async loadBlockchainData() {
const web3 = window.web3
const accounts = await web3.eth.getAccounts()
this.setState({ account: accounts[0] })
// Load smart contract
const networkId = await web3.eth.net.getId()
const networkData = MemoryToken.networks[networkId]
if (networkData) {
const abi = MemoryToken.abi
const address = networkData.address
const token = new web3.eth.Contract(abi, address)
this.setState({ token })
const totalSupply = await token.methods.totalSupply().call()
this.setState({ totalSupply })
// Load Tokens
let balanceOf = await token.methods.balanceOf(accounts[0]).call()
for (let i = 0; i < balanceOf; i++) {
let id = await token.methods.tokenOfOwnerByIndex(accounts[0], i).call()
let tokenURI = await token.methods.tokenURI(id).call()
this.setState({
tokenURIs: [...this.state.tokenURIs, tokenURI]
})
}
} else {
alert('Smart contract not deployed to detected network.')
}
}
chooseImage = (cardId) => {
cardId = cardId.toString()
if (this.state.cardsWon.includes(cardId)) {
return window.location.origin + '/images/white.png'
}
else if (this.state.cardsChosenId.includes(cardId)) {
return CARD_ARRAY[cardId].img
} else {
return window.location.origin + '/images/blank.png'
}
}
flipCard = async (cardId) => {
let alreadyChosen = this.state.cardsChosen.length
this.setState({
cardsChosen: [...this.state.cardsChosen, this.state.cardArray[cardId].name],
cardsChosenId: [...this.state.cardsChosenId, cardId]
})
if (alreadyChosen === 1) {
setTimeout(this.checkForMatch, 100)
}
}
checkForMatch = async () => {
const optionOneId = this.state.cardsChosenId[0]
const optionTwoId = this.state.cardsChosenId[1]
if (optionOneId == optionTwoId) {
alert('You have clicked the same image!')
} else if (this.state.cardsChosen[0] === this.state.cardsChosen[1]) {
alert('You found a match')
this.state.token.methods.mint(
this.state.account,
window.location.origin + CARD_ARRAY[optionOneId].img.toString()
)
.send({ from: this.state.account })
.on('transactionHash', (hash) => {
this.setState({
cardsWon: [...this.state.cardsWon, optionOneId, optionTwoId],
tokenURIs: [...this.state.tokenURIs, CARD_ARRAY[optionOneId].img]
})
})
} else {
alert('Sorry, try again')
}
this.setState({
cardsChosen: [],
cardsChosenId: []
})
if (this.state.cardsWon.length === CARD_ARRAY.length) {
alert('Congratulations! You found them all!')
}
}
constructor(props) {
super(props)
this.state = {
account: '0x0',
token: null,
totalSupply: 0,
tokenURIs: [],
cardArray: [],
cardsChosen: [],
cardsChosenId: [],
cardsWon: []
}
}
render() {
return (
<div>
<nav className="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
<a
className="navbar-brand col-sm-3 col-md-2 mr-0"
href="http://www.dappuniversity.com/bootcamp"
target="_blank"
rel="noopener noreferrer"
>
<img src={brain} width="30" height="30" className="d-inline-block align-top" alt="" />
Memory Tokens
</a>
<ul className="navbar-nav px-3">
<li className="nav-item text-nowrap d-none d-sm-none d-sm-block">
<small className="text-muted"><span id="account">{this.state.account}</span></small>
</li>
</ul>
</nav>
<div className="container-fluid mt-5">
<div className="row">
<main role="main" className="col-lg-12 d-flex text-center">
<div className="content mr-auto ml-auto">
<h1 className="d-4">Start matching now!</h1>
<div className="grid mb-4" >
{this.state.cardArray.map((card, key) => {
return (
<img
key={key}
src={this.chooseImage(key)}
data-id={key}
onClick={(event) => {
let cardId = event.target.getAttribute('data-id')
if (!this.state.cardsWon.includes(cardId.toString())) {
this.flipCard(cardId)
}
}}
/>
)
})}
</div>
<div>
<h5>Tokens Collected:<span id="result"> {this.state.tokenURIs.length}</span></h5>
<div className="grid mb-4" >
{this.state.tokenURIs.map((tokenURI, key) => {
return (
<img
key={key}
src={tokenURI}
/>
)
})}
</div>
</div>
</div>
</main>
</div>
</div>
</div>
);
}
}
export default App;
Sunday, October 10, 2021
Ethereum Programming 19 card flip game
mismatch
find a match
find another match
//src/components/app.js
import React, { Component } from 'react';
import Web3 from 'web3'
import './App.css';
import MemoryToken from '../abis/MemoryToken.json'
import brain from '../brain.png'
const CARD_ARRAY = [
{
name: 'fries',
img: '/images/fries.png'
},
{
name: 'cheeseburger',
img: '/images/cheeseburger.png'
},
{
name: 'ice-cream',
img: '/images/ice-cream.png'
},
{
name: 'pizza',
img: '/images/pizza.png'
},
{
name: 'milkshake',
img: '/images/milkshake.png'
},
{
name: 'hotdog',
img: '/images/hotdog.png'
},
{
name: 'fries',
img: '/images/fries.png'
},
{
name: 'cheeseburger',
img: '/images/cheeseburger.png'
},
{
name: 'ice-cream',
img: '/images/ice-cream.png'
},
{
name: 'pizza',
img: '/images/pizza.png'
},
{
name: 'milkshake',
img: '/images/milkshake.png'
},
{
name: 'hotdog',
img: '/images/hotdog.png'
}
]
class App extends Component {
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
this.setState({ cardArray: CARD_ARRAY.sort(() => 0.5 - Math.random()) })
}
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
await window.ethereum.enable()
}
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
}
else {
window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
}
async loadBlockchainData() {
const web3 = window.web3
const accounts = await web3.eth.getAccounts()
this.setState({ account: accounts[0] })
// Load smart contract
const networkId = await web3.eth.net.getId()
const networkData = MemoryToken.networks[networkId]
if (networkData) {
const abi = MemoryToken.abi
const address = networkData.address
const token = new web3.eth.Contract(abi, address)
this.setState({ token })
const totalSupply = await token.methods.totalSupply().call()
this.setState({ totalSupply })
// Load Tokens
let balanceOf = await token.methods.balanceOf(accounts[0]).call()
for (let i = 0; i < balanceOf; i++) {
let id = await token.methods.tokenOfOwnerByIndex(accounts[0], i).call()
let tokenURI = await token.methods.tokenURI(id).call()
this.setState({
tokenURIs: [...this.state.tokenURIs, tokenURI]
})
}
} else {
alert('Smart contract not deployed to detected network.')
}
}
chooseImage = (cardId) => {
cardId = cardId.toString()
if (this.state.cardsWon.includes(cardId)) {
return window.location.origin + '/images/white.png'
}
else if (this.state.cardsChosenId.includes(cardId)) {
return CARD_ARRAY[cardId].img
} else {
return window.location.origin + '/images/blank.png'
}
}
flipCard = async (cardId) => {
let alreadyChosen = this.state.cardsChosen.length
this.setState({
cardsChosen: [...this.state.cardsChosen, this.state.cardArray[cardId].name],
cardsChosenId: [...this.state.cardsChosenId, cardId]
})
if (alreadyChosen === 1) {
setTimeout(this.checkForMatch, 100)
}
}
checkForMatch = async () => {
const optionOneId = this.state.cardsChosenId[0]
const optionTwoId = this.state.cardsChosenId[1]
if (optionOneId == optionTwoId) {
alert('You have clicked the same image!')
} else if (this.state.cardsChosen[0] === this.state.cardsChosen[1]) {
alert('You found a match')
this.setState({
cardsWon: [...this.state.cardsWon, optionOneId, optionTwoId],
})
} else {
alert('Sorry, try again')
}
this.setState({
cardsChosen: [],
cardsChosenId: []
})
if (this.state.cardsWon.length === CARD_ARRAY.length) {
alert('Congratulations! You found them all!')
}
}
constructor(props) {
super(props)
this.state = {
account: '0x0',
token: null,
totalSupply: 0,
tokenURIs: [],
cardArray: [],
cardsChosen: [],
cardsChosenId: [],
cardsWon: []
}
}
render() {
return (
<div>
<nav className="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
<a
className="navbar-brand col-sm-3 col-md-2 mr-0"
href="http://www.dappuniversity.com/bootcamp"
target="_blank"
rel="noopener noreferrer"
>
<img src={brain} width="30" height="30" className="d-inline-block align-top" alt="" />
Memory Tokens
</a>
<ul className="navbar-nav px-3">
<li className="nav-item text-nowrap d-none d-sm-none d-sm-block">
<small className="text-muted"><span id="account">{this.state.account}</span></small>
</li>
</ul>
</nav>
<div className="container-fluid mt-5">
<div className="row">
<main role="main" className="col-lg-12 d-flex text-center">
<div className="content mr-auto ml-auto">
<h1 className="d-4">Edit this file in App.js!</h1>
<div className="grid mb-4" >
{this.state.cardArray.map((card, key) => {
return (
<img
key={key}
src={this.chooseImage(key)}
data-id={key}
onClick={(event) => {
let cardId = event.target.getAttribute('data-id')
if (!this.state.cardsWon.includes(cardId.toString())) {
this.flipCard(cardId)
}
}}
/>
)
})}
</div>
<div>
{/* Code goes here... */}
<div className="grid mb-4" >
{/* Code goes here... */}
</div>
</div>
</div>
</main>
</div>
</div>
</div>
);
}
}
export default App;
rerference:
Subscribe to:
Posts (Atom)