Tuesday, September 28, 2021

Ethereum Programming 14 tip author

tipper send 1 ether to author
//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
  );

  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

Best In Town Marathon

美丽的标价

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
//cmd
truffle 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:

Tuesday, September 21, 2021

中秋晚会 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 --reset
truffle 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:

Legendary Eats Marathon

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:

DEFI

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

Sunday, September 12, 2021

Ethereum Programming 2 transfer dapp and dai

truffle migrate --reset

truffle console 
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:

Monday, September 6, 2021

壮美广西



Billionaire Lifestyle 6

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: