Thursday, September 30, 2021
Tuesday, September 28, 2021
Ethereum Programming 14 tip author
tipper send 1 ether to author
//src/contracts/Decentragram.solpragma solidity ^0.5.0;
contract Decentragram {
// Code goes here...
string public name = "Decentragram";
uint public imageCount = 0;
mapping(uint => Image) public images;
struct Image{
uint id;
string hash;
string description;
uint tipAmount;
address payable author;
}
event ImageCreated(
uint id,
string hash,
string description,
uint tipAmount,
address payable author
);
event ImageTipped(
uint id,
string hash,
string description,
uint tipAmount,
address payable author
);
function uploadImage(string memory _imgHash, string memory _description) public {
require(bytes(_imgHash).length > 0);
require(bytes(_description).length > 0);
require(msg.sender != address(0x0));
imageCount++;
images[imageCount] = Image(imageCount, _imgHash, _description, 0, msg.sender);
emit ImageCreated(imageCount, _imgHash, _description, 0, msg.sender);
}
function tipImageOwner(uint _id) public payable{
require(_id > 0 && _id <= imageCount);
Image memory _image = images[_id];
address payable _author = _image.author;
address(_author).transfer(msg.value);
_image.tipAmount = _image.tipAmount + msg.value;
images[_id] = _image;
emit ImageTipped(_id, _image.hash, _image.description, _image.tipAmount, _author);
}
}
-------------------------
//test/test.js
const { assert } = require('chai')
const Decentragram = artifacts.require('./Decentragram.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Decentragram', ([deployer, author, tipper]) => {
let decentragram
before(async () => {
decentragram = await Decentragram.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await decentragram.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await decentragram.name()
assert.equal(name, 'Decentragram')
})
})
describe('images', async () => {
let result, imageCount
const hash = 'abc123'
before(async () => {
result = await decentragram.uploadImage(hash, 'Image description', { from: author })
imageCount = await decentragram.imageCount()
})
it('create images', async () => {
//console.log(result)
//console.log(result.logs[0].args)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), imageCount.toNumber(), 'id is correct')
assert.equal(event.hash, hash, 'Hash is correct')
assert.equal(event.description, 'Image description', 'description is correct')
assert.equal(event.tipAmount, '0', 'tip amount is correct')
assert.equal(event.author, author, 'author is correct')
await decentragram.uploadImage('', 'Image description', { from: author }).should.be.rejected;
await decentragram.uploadImage('Image hash', '', { from: author }).should.be.rejected;
await decentragram.uploadImage('Image hash', 'Image description', { from: '' }).should.be.rejected;
})
it('lists images', async () => {
const image = await decentragram.images(imageCount)
assert.equal(image.id.toNumber(), imageCount.toNumber(), 'id is correct')
assert.equal(image.hash, hash, 'Hash is correct')
assert.equal(image.description, 'Image description', 'description is correct')
assert.equal(image.tipAmount, '0', 'tip amount is correct')
assert.equal(image.author, author, 'author is correct')
})
it('allows users to tip images', async () => {
// Track the author balance before purchase
let oldAuthorBalance
oldAuthorBalance = await web3.eth.getBalance(author)
oldAuthorBalance = new web3.utils.BN(oldAuthorBalance)
//console.log(imageCount.toNumber(), author, tipper)
result = await decentragram.tipImageOwner(imageCount, { from: tipper, value: web3.utils.toWei('1', 'Ether') })
// SUCCESS
const event = result.logs[0].args
assert.equal(event.id.toNumber(), imageCount.toNumber(), 'id is correct')
assert.equal(event.hash, hash, 'Hash is correct')
assert.equal(event.description, 'Image description', 'description is correct')
assert.equal(event.tipAmount, '1000000000000000000', 'tip amount is correct')
assert.equal(event.author, author, 'author is correct')
// Check that author received funds
let newAuthorBalance
newAuthorBalance = await web3.eth.getBalance(author)
newAuthorBalance = new web3.utils.BN(newAuthorBalance)
let tipImageOwner
tipImageOwner = web3.utils.toWei('1', 'Ether')
tipImageOwner = new web3.utils.BN(tipImageOwner)
const expectedBalance = oldAuthorBalance.add(tipImageOwner)
assert.equal(newAuthorBalance.toString(), expectedBalance.toString())
// FAILURE: Tries to tip a image that does not exist
await decentragram.tipImageOwner(99, { from: tipper, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
})
})
})
------------------
//logs
Contract: Decentragram
deployment
√ deploys successfully
√ has a name (136ms)
images
√ create images (1092ms)
√ lists images (104ms)
√ allows users to tip images (602ms)
5 passing (3s)
reference:
Sunday, September 26, 2021
Ethereum Programming 13 upload image 2
//cmd -console.log(result)
PS C:\Users\zchen\Programming\decentragram-starter-code> truffle test
Using network 'development'.
Compiling your contracts...
===========================
> Compiling .\src\contracts\Decentragram.sol
> Compiling .\src\contracts\Decentragram.sol
> Compiling .\src\contracts\Migrations.sol
> Artifacts written to C:\Users\zchen\AppData\Local\Temp\test--14908-izXoOAEen8OE
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
Contract: Decentragram
deployment
√ deploys successfully
√ has a name (190ms)
images
{
tx: '0xdeaed902492c5399b6b4dd719a5de01351f560ec03c5776dd269e6754f8de3b4',
receipt: {
transactionHash: '0xdeaed902492c5399b6b4dd719a5de01351f560ec03c5776dd269e6754f8de3b4',
transactionIndex: 0,
blockHash: '0xad50fed8fbaf6b2b7cbe3d7533837f290a671ace2211c34f7378c9fb13389425',
blockNumber: 45,
from: '0x2ebfb7af01da3f8e73d2938a928289f2ef633c4e',
to: '0x6b70d1407fcffa192f9b18658abe485f4db6dac2',
gasUsed: 134507,
cumulativeGasUsed: 134507,
contractAddress: null,
logs: [ [Object] ],
status: true,
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001000000000000000000000000000000000008800000000000000000000000000000040000',
rawLogs: [ [Object] ]
},
logs: [
{
logIndex: 0,
transactionIndex: 0,
transactionHash: '0xdeaed902492c5399b6b4dd719a5de01351f560ec03c5776dd269e6754f8de3b4',
blockHash: '0xad50fed8fbaf6b2b7cbe3d7533837f290a671ace2211c34f7378c9fb13389425',
blockNumber: 45,
address: '0x6B70d1407fcfFa192F9b18658ABE485f4Db6Dac2',
type: 'mined',
id: 'log_2d9f031a',
event: 'ImageCreated',
args: [Result]
}
]
}
√ create images
3 passing (782ms)
----------------------------
//cmd - console.log(result.logs[0].args)
PS C:\Users\zchen\Programming\decentragram-starter-code> truffle test
Using network 'development'.
Compiling your contracts...
===========================
> Compiling .\src\contracts\Decentragram.sol
> Compiling .\src\contracts\Decentragram.sol
> Compiling .\src\contracts\Migrations.sol
> Artifacts written to C:\Users\zchen\AppData\Local\Temp\test--14816-pzQlEL64rrKB
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
Contract: Decentragram
deployment
√ deploys successfully
√ has a name (203ms)
images
Result {
'0': BN {
negative: 0,
words: [ 1, <1 empty item> ],
length: 1,
red: null
},
'1': 'abc123',
'2': 'Image description',
'3': BN {
negative: 0,
words: [ 0, <1 empty item> ],
length: 1,
red: null
},
'4': '0x2EbFB7Af01Da3F8E73D2938A928289F2ef633c4E',
__length__: 5,
id: BN {
negative: 0,
words: [ 1, <1 empty item> ],
length: 1,
red: null
},
hash: 'abc123',
description: 'Image description',
tipAmount: BN {
negative: 0,
words: [ 0, <1 empty item> ],
length: 1,
red: null
},
author: '0x2EbFB7Af01Da3F8E73D2938A928289F2ef633c4E'
}
√ create images
3 passing (757ms)
---------------------------
//test/test.js
const { assert } = require('chai')
const Decentragram = artifacts.require('./Decentragram.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Decentragram', ([deployer, author, tipper]) => {
let decentragram
before(async () => {
decentragram = await Decentragram.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await decentragram.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await decentragram.name()
assert.equal(name, 'Decentragram')
})
})
describe('images', async () => {
let result, imageCount
const hash = 'abc123'
before(async () => {
result = await decentragram.uploadImage(hash, 'Image description', { from: author })
imageCount = await decentragram.imageCount()
})
it('create images', async () => {
//console.log(result)
//console.log(result.logs[0].args)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), imageCount.toNumber(), 'id is correct')
assert.equal(event.hash, hash, 'Hash is correct')
assert.equal(event.description, 'Image description', 'description is correct')
assert.equal(event.tipAmount, '0', 'tip amount is correct')
assert.equal(event.author, author, 'author is correct')
})
})
})
------------------------
//src/contracts/Decentragram.sol
pragma solidity ^0.5.0;
contract Decentragram {
// Code goes here...
string public name = "Decentragram";
uint public imageCount = 0;
mapping(uint => Image) public images;
struct Image{
uint id;
string hash;
string description;
uint tipAmount;
address payable author;
}
event ImageCreated(
uint id,
string hash,
string description,
uint tipAmount,
address payable author
);
function uploadImage(string memory _imgHash, string memory _description) public {
imageCount++;
images[imageCount] = Image(imageCount, _imgHash, _description, 0, msg.sender);
emit ImageCreated(imageCount, _imgHash, _description, 0, msg.sender);
}
}
reference:
Ethereum Programming 12 upload image 1
//cmd
truffle test
Contract: Decentragram
deployment
√ deploys successfully
√ has a name (220ms)
images
Result {
'0': BN {
negative: 0,
words: [ 1, <1 empty item> ],
length: 1,
red: null
},
'1': 'abc123',
'2': 'hello',
'3': BN {
negative: 0,
words: [ 0, <1 empty item> ],
length: 1,
red: null
},
'4': '0x0000000000000000000000000000000000000000',
id: BN {
negative: 0,
words: [ 1, <1 empty item> ],
length: 1,
red: null
},
hash: 'abc123',
description: 'hello',
tipAmount: BN {
negative: 0,
words: [ 0, <1 empty item> ],
length: 1,
red: null
},
author: '0x0000000000000000000000000000000000000000'
}
√ create images (583ms)
-------------------------
//test/test.js
const Decentragram = artifacts.require('./Decentragram.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Decentragram', ([deployer, author, tipper]) => {
let decentragram
before(async () => {
decentragram = await Decentragram.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await decentragram.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await decentragram.name()
assert.equal(name, 'Decentragram')
})
})
describe('images', async () => {
let result
it('create images', async () => {
result = await decentragram.uploadImage()
let image = await decentragram.images(1)
console.log(image)
})
})
})
--------------------------------
//src/contracts/Decentragram.sol
pragma solidity ^0.5.0;
contract Decentragram {
// Code goes here...
string public name = "Decentragram";
mapping(uint => Image) public images;
struct Image{
uint id;
string hash;
string description;
uint tipAmount;
address payable author;
}
function uploadImage() public {
images[1] = Image(1, 'abc123', 'hello', 0, address(0x0));
}
}
reference:
Saturday, September 25, 2021
Ethereum Programming 11 decentragram 1
//cmd
truffle migrate --reset
truffle test
Contract: Decentragram
deployment
√ deploys successfully
√ has a name (203ms)
2 passing (291ms)
--------------------------------
//migrations/2_deploy_contracts.js
const Decentragram = artifacts.require("Decentragram");
module.exports = function (deployer) {
deployer.deploy(Decentragram);
};
---------------------------
//src/contracs/Decentragram.sol
pragma solidity ^0.5.0;
contract Decentragram {
// Code goes here...
string public name = "Decentragram";
}
----------------------
//test/test.js
const Decentragram = artifacts.require('./Decentragram.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Decentragram', ([deployer, author, tipper]) => {
let decentragram
before(async () => {
decentragram = await Decentragram.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await decentragram.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await decentragram.name()
assert.equal(name, 'Decentragram')
})
})
})
reference:
Friday, September 24, 2021
Ethereum Programming 10 generate interest
investor deposit 100mDai and earned 100Dapp
investor earned another 100Dapp
investor withdraw principle 100mDai, interest 200Dapp left in token farm
//cmdtruffle exec scripts/issue-token.js
------------------------
//scripts/issue-token.js
const TokenFarm = artifacts.require('TokenFarm')
module.exports = async function (callback) {
let tokenFarm = await TokenFarm.deployed()
await tokenFarm.issueTokens()
console.log("Tokens issued!")
callback()
}
------------------------
//src/contracts/TokenFarm.sol
pragma solidity ^0.5.0;
import "./DappToken.sol";
import "./DaiToken.sol";
contract TokenFarm{
string public name = "Dapp Token Farm";
DappToken public dappToken;
DaiToken public daiToken;
address public owner;
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 > 0, "amount greater than 0");
daiToken.transferFrom(msg.sender, address(this), _amount);
stakingBalance[msg.sender] = stakingBalance[msg.sender] + _amount;
if(!hasStaked[msg.sender]){
stakers.push(msg.sender);
}
isStaking[msg.sender] = true;
hasStaked[msg.sender] = true;
}
function unstakeTokens() public {
uint balance = stakingBalance[msg.sender];
require(balance > 0, "staking balance greater than 0");
daiToken.transfer(msg.sender, balance);
stakingBalance[msg.sender] = 0;
isStaking[msg.sender] = false;
}
function issueTokens() public {
require(msg.sender == owner, "caller must be the owner");
for (uint i=0; i<stakers.length; i++){
uint balance = stakingBalance[stakers[i]];
if(balance > 0){
dappToken.transfer(stakers[i], balance);
}
}
}
}
reference:
Wednesday, September 22, 2021
Tuesday, September 21, 2021
Ethereum Programming 9 react UI
investor has 100mDai
deposit 30mDai
token farm owner approves deposit
30mDai deposited
investor agrees to pay gas fee
investor has 70mDai in his account, and 30mDai in token farm.
investor withdraw from token farm
investor has 100mDai in his account
//src/app.js
import React, { Component } from 'react'
import Web3 from 'web3'
import DaiToken from '../abis/DaiToken.json'
import DappToken from '../abis/DappToken.json'
import TokenFarm from '../abis/TokenFarm.json'
import Navbar from './Navbar'
import Main from './Main'
import './App.css'
class App extends Component {
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
}
async loadBlockchainData() {
const web3 = window.web3
const accounts = await web3.eth.getAccounts()
console.log(accounts)
this.setState({ account: accounts[0] })
const networkId = await web3.eth.net.getId()
// Load DaiToken
const daiTokenData = DaiToken.networks[networkId]
if (daiTokenData) {
const daiToken = new web3.eth.Contract(DaiToken.abi, daiTokenData.address)
this.setState({ daiToken })
let daiTokenBalance = await daiToken.methods.balanceOf(this.state.account).call()
this.setState({ daiTokenBalance: daiTokenBalance.toString() })
} else {
window.alert('DaiToken contract not deployed to detected network.')
}
// Load DappToken
const dappTokenData = DappToken.networks[networkId]
if (dappTokenData) {
const dappToken = new web3.eth.Contract(DappToken.abi, dappTokenData.address)
this.setState({ dappToken })
let dappTokenBalance = await dappToken.methods.balanceOf(this.state.account).call()
this.setState({ dappTokenBalance: dappTokenBalance.toString() })
} else {
window.alert('DappToken contract not deployed to detected network.')
}
// Load TokenFarm
const tokenFarmData = TokenFarm.networks[networkId]
if (tokenFarmData) {
const tokenFarm = new web3.eth.Contract(TokenFarm.abi, tokenFarmData.address)
this.setState({ tokenFarm })
let stakingBalance = await tokenFarm.methods.stakingBalance(this.state.account).call()
this.setState({ stakingBalance: stakingBalance.toString() })
} else {
window.alert('TokenFarm contract not deployed to detected network.')
}
this.setState({ loading: false })
}
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!')
}
}
stakeTokens = (amount) => {
this.setState({ loading: true })
this.state.daiToken.methods.approve(this.state.tokenFarm._address, amount).send({ from: this.state.account }).on('transactionHash', (hash) => {
this.state.tokenFarm.methods.stakeTokens(amount).send({ from: this.state.account }).on('transactionHash', (hash) => {
this.setState({ loading: false })
})
})
}
unstakeTokens = (amount) => {
this.setState({ loading: true })
this.state.tokenFarm.methods.unstakeTokens().send({ from: this.state.account }).on('transactionHash', (hash) => {
this.setState({ loading: false })
})
}
constructor(props) {
super(props)
this.state = {
account: '0x0',
daiToken: {},
dappToken: {},
tokenFarm: {},
daiTokenBalance: '0',
dappTokenBalance: '0',
stakingBalance: '0',
loading: true
}
}
render() {
let content
if (this.state.loading) {
content = <p id="loader" className="text-center">Loading...</p>
} else {
content = <Main
daiTokenBalance={this.state.daiTokenBalance}
dappTokenBalance={this.state.dappTokenBalance}
stakingBalance={this.state.stakingBalance}
stakeTokens={this.stakeTokens}
unstakeTokens={this.unstakeTokens}
/>
}
return (
<div>
<Navbar account={this.state.account} />
<div className="container-fluid mt-5">
<div className="row">
<main role="main" className="col-lg-12 ml-auto mr-auto" style={{ maxWidth: '600px' }}>
<div className="content mr-auto ml-auto">
<a
href="http://www.dappuniversity.com/bootcamp"
target="_blank"
rel="noopener noreferrer"
>
</a>
{content}
</div>
</main>
</div>
</div>
</div>
);
}
}
export default App;
reference:
Monday, September 20, 2021
Ethereum Programming 8 metamask
//download chrome metamask extension
//open metamask
copy secret words from ganache server
metamask import existing wallet
paste secret words from ganache server
verify metamask account 1 address is the same as ganache account 1
select custom PRC
paste ganach server url
import account
paste private key of 2nd address on ganache as investor account
account is setup
reference:
Ethereum Programming 7 scripts 1
//cmd
truffle migrate --resettruffle exec scripts/issue-token.js
//logs
Tokens issued!
------------------------
//scripts/issue-token.js
const TokenFarm = artifacts.require('TokenFarm')
module.exports = async function (callback) {
let tokenFarm = await TokenFarm.deployed()
await tokenFarm.issueTokens()
console.log("Tokens issued!")
callback()
}
reference:
Sunday, September 19, 2021
Ethereum Programming 6 withdraw, issue interest
//contracts/TokenFarm.sol
pragma solidity ^0.5.0;
import "./DappToken.sol";
import "./DaiToken.sol";
contract TokenFarm{
string public name = "Dapp Token Farm";
DappToken public dappToken;
DaiToken public daiToken;
address public owner;
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 > 0, "amount greater than 0");
daiToken.transferFrom(msg.sender, address(this), _amount);
stakingBalance[msg.sender] = stakingBalance[msg.sender] + _amount;
if(!hasStaked[msg.sender]){
stakers.push(msg.sender);
}
isStaking[msg.sender] = true;
hasStaked[msg.sender] = true;
}
function unstakeTokens() public {
uint balance = stakingBalance[msg.sender];
require(balance > 0, "staking balance greater than 0");
daiToken.transfer(msg.sender, balance);
stakingBalance[msg.sender] = 0;
isStaking[msg.sender] = false;
}
function issueTokens() public {
require(msg.sender == owner, "caller must be the owner");
for (uint i=0; i<stakers.length; i++){
uint balance = stakingBalance[stakers[i]];
if(balance > 0){
dappToken.transfer(stakers[i], balance);
}
}
}
}
--------------------------------
//test/TokenFarm.test.js
const { assert } = require('chai')
const DappToken = artifacts.require('DappToken')
const DaiToken = artifacts.require('DaiToken')
const TokenFarm = artifacts.require('TokenFarm')
require('chai')
.use(require('chai-as-promised'))
.should()
function tokens(n) {
return web3.utils.toWei(n, 'Ether')
}
contract('TokenFarm', ([owner, investor]) => {
let daiToken, dappToken, tokenFarm
before(async () => {
daiToken = await DaiToken.new()
dappToken = await DappToken.new()
tokenFarm = await TokenFarm.new(dappToken.address, daiToken.address)
await dappToken.transfer(tokenFarm.address, tokens('1000000'))
await daiToken.transfer(investor, tokens('100'), { from: owner })
})
describe('Mock Dai deployment', async () => {
it('has a name', async () => {
const name = await daiToken.name()
assert.equal(name, 'Mock DAI Token')
})
})
describe('Dapp Token deployment', async () => {
it('has a name', async () => {
const name = await dappToken.name()
assert.equal(name, 'DApp Token')
})
})
describe('Token Farm deployment', async () => {
it('has a name', async () => {
const name = await tokenFarm.name()
assert.equal(name, 'Dapp Token Farm')
})
it('contract has tokens', async () => {
let balance = await dappToken.balanceOf(tokenFarm.address)
assert.equal(balance.toString(), tokens('1000000'))
})
})
describe('Farming tokens', async () => {
it('rewards investors for staking mDai tokens', async () => {
let result
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100', 'investor Mock Dai wallet balance correct before staking'))
await daiToken.approve(tokenFarm.address, tokens('100'), { from: investor })
await tokenFarm.stakeTokens(tokens('100'), { from: investor })
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('0'), 'investor Mock DAI wallet balance correct after staking')
result = await tokenFarm.stakingBalance(investor)
assert.equal(result.toString(), tokens('100'), 'investor staking balance correct after staking')
result = await tokenFarm.isStaking(investor)
assert.equal(result.toString(), 'true', 'investor staking status correct after staking')
await tokenFarm.issueTokens({ from: owner })
result = await dappToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100'), 'investor DApp Token wallet ballance correct after staking')
await tokenFarm.issueTokens({ from: investor }).should.be.rejected;
await tokenFarm.unstakeTokens({ from: investor })
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100'), 'investor Mock DAI wallet balance correct after unstaking')
result = await daiToken.balanceOf(tokenFarm.address)
assert.equal(result.toString(), tokens('0'), 'Token Farm Mock DAI wallet balance correct after unstaking')
result = await tokenFarm.stakingBalance(investor)
assert.equal(result.toString(), tokens('0'), 'investor staking balance correct after unstaking')
result = await tokenFarm.isStaking(investor)
assert.equal(result.toString(), 'false', 'investor staking status correct after unstaking')
})
})
})
--------------------------------------
//logs
Contract: TokenFarm
Mock Dai deployment
√ has a name (243ms)
Dapp Token deployment
√ has a name (68ms)
Token Farm deployment
√ has a name (91ms)
√ contract has tokens (101ms)
Farming tokens
√ rewards investors for staking mDai tokens (3323ms)
5 passing (6s)
reference:
Saturday, September 18, 2021
Ethereum Programming 5 deposit
//contracts/TokenFarm.sol
pragma solidity ^0.5.0;
import "./DappToken.sol";
import "./DaiToken.sol";
contract TokenFarm{
string public name = "Dapp Token Farm";
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;
}
function stakeTokens(uint _amount) public{
daiToken.transferFrom(msg.sender, address(this), _amount);
stakingBalance[msg.sender] = stakingBalance[msg.sender] + _amount;
if(!hasStaked[msg.sender]){
stakers.push(msg.sender);
}
isStaking[msg.sender] = true;
hasStaked[msg.sender] = true;
}
}
--------------------------------
//test/TokenFarm.test.js
const { assert } = require('chai')
const DappToken = artifacts.require('DappToken')
const DaiToken = artifacts.require('DaiToken')
const TokenFarm = artifacts.require('TokenFarm')
require('chai')
.use(require('chai-as-promised'))
.should()
function tokens(n) {
return web3.utils.toWei(n, 'Ether')
}
contract('TokenFarm', ([owner, investor]) => {
let daiToken, dappToken, tokenFarm
before(async () => {
daiToken = await DaiToken.new()
dappToken = await DappToken.new()
tokenFarm = await TokenFarm.new(dappToken.address, daiToken.address)
await dappToken.transfer(tokenFarm.address, tokens('1000000'))
await daiToken.transfer(investor, tokens('100'), { from: owner })
})
describe('Mock Dai deployment', async () => {
it('has a name', async () => {
const name = await daiToken.name()
assert.equal(name, 'Mock DAI Token')
})
})
describe('Dapp Token deployment', async () => {
it('has a name', async () => {
const name = await dappToken.name()
assert.equal(name, 'DApp Token')
})
})
describe('Token Farm deployment', async () => {
it('has a name', async () => {
const name = await tokenFarm.name()
assert.equal(name, 'Dapp Token Farm')
})
it('contract has tokens', async () => {
let balance = await dappToken.balanceOf(tokenFarm.address)
assert.equal(balance.toString(), tokens('1000000'))
})
})
describe('Farming tokens', async () => {
it('rewards investors for staking mDai tokens', async () => {
let result
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('100', 'investor Mock Dai wallet balance correct before staking'))
await daiToken.approve(tokenFarm.address, tokens('100'), { from: investor })
await tokenFarm.stakeTokens(tokens('100'), { from: investor })
result = await daiToken.balanceOf(investor)
assert.equal(result.toString(), tokens('0'), 'investor Mock DAI wallet balance correct after staking')
result = await tokenFarm.stakingBalance(investor)
assert.equal(result.toString(), tokens('100'), 'investor staking balance correct after staking')
result = await tokenFarm.isStaking(investor)
assert.equal(result.toString(), 'true', 'investor staking status correct after staking')
})
})
})
-----------------------
//logs
Contract: TokenFarm
Mock Dai deployment
√ has a name (188ms)
Dapp Token deployment
√ has a name (126ms)
Token Farm deployment
√ has a name (95ms)
√ contract has tokens (155ms)
Farming tokens
√ rewards investors for staking mDai tokens (1107ms)
5 passing (3s)
reference;
Friday, September 17, 2021
Ethereum Programming 4 testing verify token name and balance
//TokenFarm.test.js
const { assert } = require('chai')
const DappToken = artifacts.require('DappToken')
const DaiToken = artifacts.require('DaiToken')
const TokenFarm = artifacts.require('TokenFarm')
require('chai')
.use(require('chai-as-promised'))
.should()
function tokens(n) {
return web3.utils.toWei(n, 'Ether')
}
contract('TokenFarm', ([owner, investor]) => {
let daiToken, dappToken, tokenFarm
before(async () => {
daiToken = await DaiToken.new()
dappToken = await DappToken.new()
tokenFarm = await TokenFarm.new(dappToken.address, daiToken.address)
await dappToken.transfer(tokenFarm.address, tokens('1000000'))
await daiToken.transfer(investor, tokens('100'), { from: owner })
})
describe('Mock Dai deployment', async () => {
it('has a name', async () => {
const name = await daiToken.name()
assert.equal(name, 'Mock DAI Token')
})
})
describe('Dapp Token deployment', async () => {
it('has a name', async () => {
const name = await dappToken.name()
assert.equal(name, 'DApp Token')
})
})
describe('Token Farm deployment', async () => {
it('has a name', async () => {
const name = await tokenFarm.name()
assert.equal(name, 'Dapp Token Farm')
})
it('contract has tokens', async () => {
let balance = await dappToken.balanceOf(tokenFarm.address)
assert.equal(balance.toString(), tokens('1000000'))
})
})
})
----------------------------
//logs
Contract: TokenFarm
Mock Dai deployment
√ has a name (203ms)
Dapp Token deployment
√ has a name (98ms)
Token Farm deployment
√ has a name (149ms)
√ contract has tokens (96ms)
4 passing (3s)
reference:
Wednesday, September 15, 2021
Ethereum Programming 3 testing 1
truffle test
Contract: TokenFarm
Mock Dai deployment
1) has a name
> No events were emitted
0 passing (662ms)
1 failing
1) Contract: TokenFarm
Mock Dai deployment
has a name:
AssertionError: expected 'Mock DAI Token' to equal 'Mock Dai Token'
+ expected - actual
-Mock DAI Token
+Mock Dai Token
----------------
//TokenFarm.test.js
const { assert } = require('chai')
const DappToken = artifacts.require('DappToken')
const DaiToken = artifacts.require('DaiToken')
const TokenFarm = artifacts.require('TokenFarm')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('TokenFarm', (accounts) => {
let daiToken
before(async () => {
daiToken = await DaiToken.new()
})
describe('Mock Dai deployment', async () => {
it('has a name', async () => {
const name = await daiToken.name()
assert.equal(name, 'Mock DAI Token')
})
})
})
reference:
https://www.youtube.com/watch?v=XLahq4qyors
Tuesday, September 14, 2021
Sunday, September 12, 2021
Ethereum Programming 2 transfer dapp and dai
truffle migrate --reset
tokenFarm = await TokenFarm.deployed()
truffle(development)> tokenFarm.address
'0x689cB867e929Cdd1c69b78B27fb11DAb86B6393e'
truffle(development)> name = tokenFarm.name()
'Dapp Token Farm'
truffle(development)> mDai = await DaiToken.deployed()
accounts = await web3.eth.getAccounts()
truffle(development)> accounts[1]
'0xBC7000c582225B1086020043f35a8bcE1DA910F6'
truffle(development)> balance = await mDai.balanceOf(accounts[1])
undefined
truffle(development)> balance
BN {
negative: 0,
words: [ 51380224, 30903128, 22204, <1 empty item> ],
length: 3,
red: null
}
truffle(development)> balance.toString()
'100000000000000000000'
truffle(development)> formattedBalance = web3.utils.fromWei(balance)
'100'
truffle(development)> web3.utils.toWei('1.5', 'Ether')
'1500000000000000000'
---------------------
//migrations/2_deploy_contract.js
const DappToken = artifacts.require('DappToken')
const DaiToken = artifacts.require('DaiToken')
const TokenFarm = artifacts.require('TokenFarm')
module.exports = async function (deployer, network, accounts) {
// Deploy Mock DAI Token
await deployer.deploy(DaiToken)
const daiToken = await DaiToken.deployed()
// Deploy Dapp Token
await deployer.deploy(DappToken)
const dappToken = await DappToken.deployed()
// Deploy TokenFarm
await deployer.deploy(TokenFarm, dappToken.address, daiToken.address)
const tokenFarm = await TokenFarm.deployed()
// Transfer all tokens to TokenFarm (1 million)
await dappToken.transfer(tokenFarm.address, '1000000000000000000000000')
// Transfer 100 Mock DAI tokens to investor
await daiToken.transfer(accounts[1], '100000000000000000000')
}
--------------------------
//src/componenets/contracts
pragma solidity ^0.5.0;
import "./DappToken.sol";
import "./DaiToken.sol";
contract TokenFarm{
string public name = "Dapp Token Farm";
DappToken public dappToken;
DaiToken public daiToken;
constructor(DappToken _dappToken, DaiToken _daiToken) public{
dappToken = _dappToken;
daiToken = _daiToken;
}
}
reference:
Saturday, September 11, 2021
Ethereum Programming 1
terminal
truffle compile
truffle migrate
truffle console
truffle(development)> tokenFarm = await TokenFarm.deployed()
truffle(development)> tokenFarm
metamask
github code
reference:
Friday, September 10, 2021
Thursday, September 9, 2021
Monday, September 6, 2021
kivy 51 add ship
#galaxy.py
import random
from kivy import platform
from kivy.app import App
from kivy.core.window import Window
from kivy.graphics import Line, Rectangle, Color, Quad, Triangle
from kivy.metrics import dp
from kivy.properties import NumericProperty, Clock
from kivy.uix.widget import Widget
class Galaxy(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.n_vlines = 5
self.n_hlines = 15
self.space_vlines = dp(150)
self.space_hlines = dp(100)
self.speed_hl = 10
self.step_hl = 0
self.clock = 0.05
self.speed_vl = 10
self.step_vl = 0
self.direction_vl = 1
self.click_press = False
self.start_x = 0
self.shift_x = 0
self.shift_y = 0
self.n_keydown = 0
self.tiles = []
for i in range(12):
self.tiles.append({"x": 2, "y": i})
with self.canvas:
self.vlines = []
self.hlines = []
for i in range(self.n_vlines+1):
vline = Line(points=(0,0,0,100))
self.vlines.append(vline)
for j in range(self.n_hlines):
hline = Line(points=(0,0,100,0))
self.hlines.append(hline)
self.rect_l = Rectangle(pos =(0,0), size=(0,0))
self.rect_r = Rectangle(pos=(0, 0), size=(0, 0))
self.quads = []
Color(0,1,0)
for n in range(30):
quad = Quad()
quad.points = [0, 0, 0, 0, 0, 0, 0, 0]
self.quads.append((quad))
Color(0,0,1)
self.ship = Triangle()
Clock.schedule_interval(self.update, self.clock)
if platform in ('linux', 'win', 'macosx'):
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down=self._on_keyboard_down)
self._keyboard.bind(on_key_up=self._on_keyboard_up)
def on_size(self, *args):
self.update(0.2)
def on_touch_down(self, touch):
self.click_press = True
if touch.x < self.width/2:
self.rect_l.pos = (0, self.center_y-dp(50))
self.rect_l.size = (dp(100), dp(100))
self.direction_vl = abs(self.direction_vl)
self.update(0.2)
else:
self.rect_r.pos = (self.width-dp(100), self.center_y - dp(50))
self.rect_r.size = (dp(100), dp(100))
self.direction_vl = -abs(self.direction_vl)
self.update(0.2)
def on_touch_up(self, touch):
self.click_press = False
self.rect_l.size=(0,0)
self.rect_r.size = (0, 0)
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard.unbind(on_key_down=self._on_keyboard_up)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
print(self.n_keydown)
self.click_press = False
if self.n_keydown>0: return False
#print("keyboard down")
if keycode[1] == 'left':
self.click_press = True
self.n_keydown += 1
self.rect_l.pos = (0, self.center_y - dp(50))
self.rect_l.size = (dp(100), dp(100))
#self.direction_vl = abs(self.direction_vl)
self.direction_vl = self.space_vlines/self.speed_hl
elif keycode[1] == 'right':
self.n_keydown += 1
self.click_press = True
self.rect_r.pos = (self.width - dp(100), self.center_y - dp(50))
self.rect_r.size = (dp(100), dp(100))
#self.direction_vl = -abs(self.direction_vl)
self.direction_vl = -self.space_vlines/self.speed_hl
return True
def _on_keyboard_up(self, *args):
#print(*args)
#print("keyboard up")
self.n_keydown=0
self.update(0.2)
self.rect_l.size = (0, 0)
self.rect_r.size = (0, 0)
self.click_press = False
return True
def perspective_transform(self, x, y):
#return x, y
ratio = (self.height-y)/self.height
tx = ratio*(self.center_x-x)
ty = ratio**2
return self.center_x-tx, 0.8*self.height*(1-ty)
def tile(self, a, b, n):
x0 = self.start_x + a * self.space_vlines + self.shift_x
y0 = b * self.space_hlines - self.shift_y
x1 = x0
y1 = y0 + self.space_hlines
x2 = x0 + self.space_vlines
y2 = y1
x3 = x2
y3 = y0
_, y0 = self.perspective_transform(x0, y0)
x0, _ = self.perspective_transform(x0, y0 / 0.8)
_, y1 = self.perspective_transform(x1, y1)
x1, _ = self.perspective_transform(x1, y1 / 0.8)
_, y2 = self.perspective_transform(x2, y2)
x2, _ = self.perspective_transform(x2, y2 / 0.8)
_, y3 = self.perspective_transform(x3, y3)
x3, _ = self.perspective_transform(x3, y3 / 0.8)
self.quads[n].points = [x0, y0, x1, y1, x2, y2, x3, y3]
def update(self, dt):
self.start_x = self.center_x - (int(self.n_vlines / 2)+0.5) * self.space_vlines
self.shift_x = self.speed_vl * self.step_vl
"""
if shift_x > self.width or shift_x < -self.width:
self.direction_vl = -self.direction_vl
"""
if self.click_press and self.n_keydown==0:
self.step_vl += self.direction_vl
for i in range(self.n_vlines+1):
x = self.start_x + self.space_vlines * i + self.shift_x
x1, y1, x2, y2 = x, 0, x, self.height
x1, y1 = self.perspective_transform(x1, y1)
x2, y2 = self.perspective_transform(x2, y2)
self.vlines[i].points = (x1, y1, x2, y2)
self.space_hlines = self.height / self.n_hlines
self.shift_y = self.speed_hl * self.step_hl
if self.shift_y > self.space_hlines:
self.step_hl = 0
if not self.click_press:
self.step_hl += 1
for j in range(self.n_hlines):
y = j * self.space_hlines - self.shift_y
x1, y1, x2, y2 = self.start_x + self.shift_x, y, self.width - self.start_x + self.shift_x, y
_, y1 = self.perspective_transform(x1, y1)
x1, _ = self.perspective_transform(x1, y1 / 0.8)
_, y2 = self.perspective_transform(x2, y2)
x2, _ = self.perspective_transform(x2, y2 / 0.8)
self.hlines[j].points = (x1, y1, x2, y2)
for i, tile in enumerate(self.tiles):
self.tile(tile["x"], tile["y"], i)
n_tiles = len(self.tiles)
if self.shift_y > self.space_hlines:
tile["y"] -= 1
if tile["y"] < 0:
del self.tiles[i]
self.quads[n_tiles-1].points = [0, 0, 0, 0, 0, 0, 0, 0]
if self.tiles[i+1]["y"] == 0:
del self.tiles[i+1]
self.quads[n_tiles-2].points = [0, 0, 0, 0, 0, 0, 0, 0]
tile_y = self.tiles[-1]["y"]
tile_x = self.tiles[-1]["x"] + random.randrange(-1, 2)
if tile_x < 0 or tile_x > self.n_vlines-2:
tile_x = self.tiles[-1]["x"]
if tile_x == self.tiles[-1]["x"]:
self.tiles.append({"x": tile_x, "y": tile_y + 1})
else:
self.tiles.append({"x": tile_x, "y": tile_y})
self.tiles.append({"x": tile_x, "y": tile_y + 1})
x0 = self.center_x - self.space_vlines/2
y0 = self.space_hlines
x1 = self.center_x
y1 = self.space_hlines * 2
x2 = self.center_x + self.space_vlines/2
y2 = self.space_hlines
_, y0 = self.perspective_transform(x0, y0)
x0, _ = self.perspective_transform(x0, y0 / 0.8)
_, y1 = self.perspective_transform(x1, y1)
x1, _ = self.perspective_transform(x1, y1 / 0.8)
_, y2 = self.perspective_transform(x2, y2)
x2, _ = self.perspective_transform(x2, y2 / 0.8)
self.ship.points = [x0, y0, x1, y1, x2, y2]
if self.shift_y > self.space_hlines:
self.shift_y = 0
#print(self.tiles)
class GalaxyApp(App):
pass
GalaxyApp().run()
reference:
Subscribe to:
Posts (Atom)