zoukankan      html  css  js  c++  java
  • 62、solidity环境搭建、编译及编写合约-3——2020年07月12日12:55:51

    2020年07月12日12:59:00

    2019年09月27日14:15:32

    1.通过solc工具编译合约

    1.1 先在vscode里创建sol文件

    pragma solidity ^0.4.24;
    	contract Immo{
        address public ceo;
        constructor() public {
          ceo=msg.sender;
        }
        
      }
    

    1.2.准备编译环境,sol文件都是通过solc工具编译的

    npm install solc@0.4.24 --save一定要声明版本

    github.com/ethereum/solc-js

    1.3.项目是通过react新建的

    create-react-app imooc-on-blockchain

    1.4.js脚本文件读写和编译sol

    mkdir scripts

    touch compile.js

    // 文件模块
    const fs = require('fs')
    
    const path = require('path')
    //编译模块solc
    const solc = require('solc')
    
    const contractPath = path.resolve(__dirname,'../contracts/Imooc.sol')
    
    // 获取合约文件内容
    const source = fs.readFileSync(contractPath,'utf-8')
    // 编译
    const ret = solc.compile(source)
    // console.log(ret)
      Object.keys(ret.contracts).forEach(name=>{
        //过滤掉第一个key键,它前面有一个:,不需要
        const contractName = name.slice(1)
        //创建即将要写进数据的文件路径
        const filePath = path.resolve(__dirname, `../src/compiled/${contractName}.json`)
        //同步写数据
        fs.writeFileSync(filePath,JSON.stringify(ret.contracts[name]))
        console.log(`${filePath} bingo`)
      })
    
    // arr = [{name:'react',content:'xx',{name:'vue',content:'xx'}]
    

    1.5.配置package.json

    "compile" :"node scripts/compile.js"

    image-20190927150058197

    1.6.启动服务

    npm run compile

    编译.sol文件,生成一个json(后面部署,测试等需要这些数据)

    1. bytecode

      部署合约用的数据

    2. interface接口声明

      测试使用

    2.合约自动编译

    1. 每次compile清空文件,重新生成
    2. 报错信息打印
    3. 能监听,自动compile

    2.1 安装rimraf清除模块

    npm install rimraf --save

    配置package.json

    rimraf src/compiled/* && node scripts/compile.js

    2.2 控制报错信息

    打印出error,发现errors数组长度>1

    image-20190927152634081

    则:

    if(Array.isArray(ret.errors) && ret.errors.length>0){
      // 出错了
      console.log(ret.errors[0])
    }else{
      Object.keys(ret.contracts).forEach(name=>{
        const contractName = name.slice(1)
        const filePath = path.resolve(__dirname, `../src/compiled/${contractName}.json`)
        fs.writeFileSync(filePath,JSON.stringify(ret.contracts[name]))
        console.log(`${filePath} bingo`)
      })
    }
    

    再调式的时候会出现:

    image-20190927152948353

    2.3 使用钩子precompile

    在package.json文件中

    precompile:"rimraf src/compiled/*"

    2.4 监听——使用Onchange模块

    npm install onchange --save

    "precompile": "rimraf src/compiled/* ",
    "compile": "node scripts/compile.js",
    "precompile:w": "npm run compile",
    "compile:w": "onchange 'contracts/*.sol' -- npm run compile"
    

    只要合约发生了变化,就会重新编译

    npm run compile:w

    3.编写合约——课程列表

    3.1 两个合约:课程数组,单个课程

    3.2 方法:新建课程,获取课程

    3.3 代码

      pragma solidity ^0.4.24;
      
      contract CourseList{
      address public ceo;
      address[] public courses;
      constructor() public {
        ceo = msg.sender;
      }
    
      function createCourse(string _name) public{
        address newCourse = new Course(ceo,msg.sender, _name);
        courses.push(newCourse);
      }
      // 获取课程所有地址
      function getCourse() public view returns(address[]){
        return courses;
      }
        }
    
         contract Course{
            string public name;
            constructor(string _name) public {
                name=_name;
                        }
            }
    

    4.测试合约

    4.1 虚拟节点

    ganache-cli

    4.2测试用的模块

    mocha

    4.3 编写测试用例
    const path = require('path');
    const assert = require('assert');
    
    describe('测试课程的智能', () => {
    
        it('测试1+2是否等于3', () => {
    
            assert.equal(1 + 2, 3);
        })
    })
    
    4.4 测试合约方法
    const path = require('path');
    const assert = require('assert');
    const Web3 = require('web3')
    const ganache = require('ganache-cli')
    //const BigNumber = require('bignumber.js')
    const web3 = new Web3(ganache.provider())
    // 引入合约的json
    const CourseList = require(path.resolve(__dirname, '../src/compiled/CourseList.json'))
    const Course = require(path.resolve(__dirname, '../src/compiled/Course.json'))
    
    
    // 定义几个全局变量,所有测试都需要
    let accounts
    // 实例
    let courseList
    let course
    
    describe('测试课程的智能', () => {
    
        before(async () => {
            // 测试前的数据初始化
            accounts = await web3.eth.getAccounts()
            
            console.log(accounts)
            // 1. 虚拟部署一个合约
            courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
                .deploy({ data: CourseList.bytecode })
                .send({
                    // 最后一个是创建者
                    from: accounts[9],
                    gas: '5000000'
                })
    
        })
    
        it('合约部署成功', () => {
            assert.ok(courseList.options.address)
        })
    
        it('测试添加课程', async () => {
            const oldaddress = await courseList.methods.getCourse().call()
            assert.equal(oldaddress.length, 0)
            await courseList.methods.createCourse(
                '蜗牛的React课程'
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 1)
    				console.log(address)
        })
    
    })
    
    4.5 配置package.json
    "test:w": "mocha --watch"
    
    4.6 运行指令

    npm run test:w

    4.6 测试结果

    image-20190927202842569

    2019年09月27日20:31:07

    5.添加删除课程指令

    5.1 sol文件里函数编写
     function removeCourse(uint _index) public {
         // 只有ceo能删除
        require(msg.sender == ceo);
        // 根据索引删除
        require(_index<courses.length);
      }
    
    5.2 package.json配置
        "rebuild": "npm run compile && mocha",
        "rebuild:w": "onchange 'contracts/*.sol' 'test/*.js' -- npm run rebuild"
    

    作用是当合约发生变化时,先编译再测试。

    5.3 运行

    npm run rebuild

    5.4 测试用例
    const path = require('path');
    const assert = require('assert');
    const Web3 = require('web3')
    const ganache = require('ganache-cli')
    //const BigNumber = require('bignumber.js')
    const web3 = new Web3(ganache.provider())
    // 引入合约的json
    const CourseList = require(path.resolve(__dirname, '../src/compiled/CourseList.json'))
    const Course = require(path.resolve(__dirname, '../src/compiled/Course.json'))
    
    
    // 定义几个全局变量,所有测试都需要
    let accounts
    // 实例
    let courseList
    let course
    
    describe('测试课程的智能', () => {
    
        before(async () => {
            // 测试前的数据初始化
            accounts = await web3.eth.getAccounts()
    
            console.log(accounts)
            // 1. 虚拟部署一个合约
            courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
                .deploy({ data: CourseList.bytecode })
                .send({
                    // 最后一个是创建者——重点
                    from: accounts[9],
                    gas: '5000000'
                })
    
        })
    
        it('合约部署成功', () => {
            assert.ok(courseList.options.address)
        })
    
        it('测试添加课程', async () => {
            const oldaddress = await courseList.methods.getCourse().call()
            assert.equal(oldaddress.length, 0)
            await courseList.methods.createCourse(
                '蜗牛的React课程'
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 1)
            console.log(address)
    
        })
    
        it("添加课程的属性", async () => {
            const [address] = await courseList.methods.getCourse().call()
            // 添加的课程合约的地址
            course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
            const name = await course.methods.name().call()
            assert.equal(name, '蜗牛的React课程')
        })
    
    
    
        //删除功能
        it("只能ceo能删", async () => {
            await courseList.methods.createCourse(
                '蜗牛的Vue课程'
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 2)
    
          await courseList.methods.removeCourse(0).send({
            from:accounts[9],
            gas:'5000000'
          })
          const address1 = await courseList.methods.getCourse().call()
          console.log(address1)
          assert.equal(address1.length,1)
          
        })
    
    })
    
    5.6 发现bug

    solidity提供的delete()方法删除了地址账号后,不是清除数据,而是将数据清0.

    所以得修改合约里的方法

    5.7 修改合约
      function removeCourse(uint _index) public {
         // 只有ceo能删除
        require(msg.sender == ceo);
        // 根据索引删除
        require(_index<courses.length);
        uint len = courses.length;
        for(uint i=_index;i<len-1;i++){
          courses[i] = courses[i+1];
        }
        delete courses[len-1];
        courses.length--;
      }
    
    
        }
    
    5.8 添加管理员的认证——合约方法
      function isCeo() public view returns(bool){
        return msg.sender==ceo;
      }
    
    5.9测试用例
      it('判断是不是ceo',async ()=>{
        const isCeo1 = await courseList.methods.isCeo().call({
          from :accounts[9]
        })
        const isCeo2 = await courseList.methods.isCeo().call({
          from :accounts[1]
        })
        assert.ok(isCeo1)
        assert.ok(!isCeo2)
      })
    
    5.10 运行结果

    npm run rebuild:w

    image-20190927234013228

    5.11 完整代码
    //Imooc.sol  
    pragma solidity ^0.4.24;
      
      contract CourseList{
      address public ceo;
      address[] public courses;
      constructor() public {
        ceo = msg.sender;
      }
    
      function createCourse(string _name) public{
        address newCourse = new Course(_name);
        courses.push(newCourse);
      }
      // 获取课程所有地址
      function getCourse() public view returns(address[]){
        return courses;
      }
    
      function removeCourse(uint _index) public {
         // 只有ceo能删除
        require(msg.sender == ceo);
        // 根据索引删除
        require(_index<courses.length);
        uint len = courses.length;
        for(uint i=_index;i<len-1;i++){
          courses[i] = courses[i+1];
        }
        delete courses[len-1];
        courses.length--;
      }
      function isCeo() public view returns(bool){
        return msg.sender==ceo;
      }
    
        }
         
         
         
    contract Course{
        string public name;
        constructor(string _name) public {
            name=_name;
                 }
            }
    
    //course.spec.js
    const path = require('path');
    const assert = require('assert');
    const Web3 = require('web3')
    const ganache = require('ganache-cli')
    //const BigNumber = require('bignumber.js')
    const web3 = new Web3(ganache.provider())
    // 引入合约的json
    const CourseList = require(path.resolve(__dirname, '../src/compiled/CourseList.json'))
    const Course = require(path.resolve(__dirname, '../src/compiled/Course.json'))
    
    
    // 定义几个全局变量,所有测试都需要
    let accounts
    // 实例
    let courseList
    let course
    
    describe('测试课程的智能', () => {
    
        before(async () => {
            // 测试前的数据初始化
            accounts = await web3.eth.getAccounts()
    
            console.log(accounts)
            // 1. 虚拟部署一个合约
            courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
                .deploy({ data: CourseList.bytecode })
                .send({
                    // 最后一个是创建者——重点
                    from: accounts[9],
                    gas: '5000000'
                })
    
        })
    
        it('合约部署成功', () => {
            assert.ok(courseList.options.address)
        })
    
        it('测试添加课程', async () => {
            const oldaddress = await courseList.methods.getCourse().call()
            assert.equal(oldaddress.length, 0)
            await courseList.methods.createCourse(
                '蜗牛的React课程'
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 1)
            console.log(address)
    
        })
    
        it("添加课程的属性", async () => {
            const [address] = await courseList.methods.getCourse().call()
            // 添加的课程合约的地址
            course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
            const name = await course.methods.name().call()
            assert.equal(name, '蜗牛的React课程')
        })
    
    
    
        //删除功能
        it("只能ceo能删", async () => {
            await courseList.methods.createCourse(
                '蜗牛的Vue课程'
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 2)
    
          await courseList.methods.removeCourse(0).send({
            from:accounts[9],
            gas:'5000000'
          })
          const address1 = await courseList.methods.getCourse().call()
          console.log(address1)
          assert.equal(address1.length,1)
          
        })
    
        it('判断是不是ceo',async ()=>{
            const isCeo1 = await courseList.methods.isCeo().call({
              from :accounts[9]
            })
            const isCeo2 = await courseList.methods.isCeo().call({
              from :accounts[1]
            })
            assert.ok(isCeo1)
            assert.ok(!isCeo2)
          })
          
    
    })
    

    6.完善课程的属性,添加其他属性

    6.1 添加一下属性

    课程: owner

    课程创建者 name

    课程名 content

    课程简介 target

    课程目标是募资多少 ETH

    fundingPrice 众筹价格

    price 上线价格

    img 课程头图

    video 视频

    count 多少人支持

    isOnline 是否上线

    6.2 合约里添加Course以及createCourse完善
    //Imooc.sol
    function createCourse(string _name,string _content,uint _target,uint _fundingPrice,uint _price,string _img) public{
        address newCourse = new Course(ceo,msg.sender, _name, _content, _target, 				  	_fundingPrice, _price, _img);
        courses.push(newCourse);
      }
    
    //Imooc.sol
    contract Course{
      address public ceo;
      address public owner;
      string public name;
      string public content;
      uint public target;
      uint public fundingPrice;
      uint public price;
      string public img;
      string public video;
      bool public isOnline;
      uint public count;
      constructor(address _ceo, address _owner,string _name,string _content,uint _target,uint _fundingPrice,uint _price,string _img) public{
        ceo = _ceo;
        owner = _owner;
        name = _name;
        content = _content;
        target = _target;
        fundingPrice = _fundingPrice;
        price = _price;
        img = _img;
        video = '';
        count = 0;
        isOnline = false;
      }
            }
    
    6.3 编写测试逻辑,完善属性
     it('测试添加课程', async () => {
            const oldaddress = await courseList.methods.getCourse().call()
            assert.equal(oldaddress.length, 0)
            await courseList.methods.createCourse(
                '蜗牛的React课程',
                "React+redux+reactrouter4开发招聘app",
                web3.utils.toWei('8'),
                // 众筹价格
                web3.utils.toWei('2'),
                web3.utils.toWei('4'),
                "图片的hash"
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 1)
    
        })
        it("添加课程的属性", async () => {
            const [address] = await courseList.methods.getCourse().call()
            // 添加的课程合约的地址
            course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
            const name = await course.methods.name().call()
            const content = await course.methods.content().call()
            const target = await course.methods.target().call()
            const fundingPrice = await course.methods.fundingPrice().call()
            const price = await course.methods.price().call()
            const img = await course.methods.img().call()
            const count = await course.methods.count().call()
            const isOnline = await course.methods.isOnline().call()
            assert.equal(name, '蜗牛的React课程')
            assert.equal(content, 'React+redux+reactrouter4开发招聘app')
            assert.equal(target, web3.utils.toWei('8'))
            assert.equal(fundingPrice, web3.utils.toWei('2'))
            assert.equal(price, web3.utils.toWei('4'))
            assert.equal(img, "图片的hash")
            assert.ok(!isOnline)
            assert.equal(count, 0)
        })
    
      it("只能ceo能删", async ()=>{
            await courseList.methods.createCourse(
              '蜗牛的Vue课程',
              'vue也是个好框架,简单好上手',
              web3.utils.toWei('8'),
              // 众筹价格
              web3.utils.toWei('2'),
              web3.utils.toWei('4'),
              "图片的hash1"   
              )
                  .send({
                    from:accounts[0],
                    gas:'5000000'
                  })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length,2)
        })
    

    7.用户购买课程及课程上线

    7.1 设置用户列表
        // 用户购买信息
      mapping(address=>uint) public users;
    
    7.2 用户购买合约以及课程上线

    课程上线之后众筹的钱立刻全部打给众筹者,之后再有用户购买,则进行分成。给ceo一成的利润。

    // 众筹或者购买
      function buy() public payable{
        // 1. 用户没有购买过
        require(users[msg.sender]==0);
        if(isOnline){
          // 如果上线了 必须得用上线价格购买
          require(price == msg.value);
        }else{
          // 如果上线了 必须得用众筹价格购买
          require(fundingPrice == msg.value);
        }
        users[msg.sender] = msg.value;
        // 统计人数
        count += 1;
        
        if(target <= count*fundingPrice){
            // 钱超出目标
            if(isOnline){
              // 上线之后的购买
              uint value = msg.value;
              // 分成
              ceo.transfer(value/10);
              owner.transfer(value-value/10);
            }else{
              // 没上线 第一次超出
              isOnline = true;
              // 转账
              // 上线之前的钱,都在合约内部,众筹者是拿不到的
              owner.transfer(count*fundingPrice);
    
            }
        }
      }
    
    7.3 用户获取课程详情
    // 获取详情
      function getDetail() public view returns(string,string,uint,uint,uint,string,string,uint,bool,uint){
        uint role;
        if(owner==msg.sender){
          role = 0; //课程创建者
        }else if(users[msg.sender]>0){
          role = 1; // 已购买
        }else{
          role = 2; // 没买
        }
        return (
          name,
          content,
          target,
          fundingPrice,
          price,
          img,
          video,
          count,
          isOnline,
          role
        );
      }
    
    7.4 上线之后众筹者才可以添加视频——ipfs地址
        function addVideo(string _video) public{
        require(msg.sender==owner);
        require(isOnline==true);
        video = _video;
      }
    
    7.5编译通过

    image-20190928123234719

    8.课程购买测试编写

    8.1 金钱转换

    wei

    finney

    szabo

    ether

    1 ether == 10^3 finney
    1 ether == 10^6 szabo
    1 ether == 10^18 Wei
    
    it('金钱转换',()=>{
        assert.equal(web3.utils.toWei('2'),'2000000000000000000')
      })
    
    8.2 课程购买
          it('课程购买',async()=>{
            await course.methods.buy().send({
              from:accounts[2],
              value:web3.utils.toWei('2')
            })
            const value = await course.methods.users(accounts[2]).call()
            const count = await course.methods.count().call()
            assert.equal(value,web3.utils.toWei('2'))
            assert.equal(count,1)
    
            // 输出value及users+
            console.log("钱是:")
            console.log(value)
            // console.log("uers是:")
    
            
            // 用户role的判断
            const detail = await course.methods.getDetail().call({from:accounts[0]})
            assert.equal(detail[9],0)
        
            // 课程
            console.log(detail)
            const detail2 = await course.methods.getDetail().call({from:accounts[2]})
            assert.equal(detail2[9],1)
        
            const detail3 = await course.methods.getDetail().call({from:accounts[5]})
            assert.equal(detail3[9],2)
          })
    

    image-20190928130026973

    8.3 引入bignumber.js

    npm install bignumber.js

    const BigNumber = require('bignumber.js')

    8.4 还没上线的话,钱不入账
          it('还没上线,购买的课不入账',async()=>{
            const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
            await course.methods.buy().send({
              from:accounts[3],
              value:web3.utils.toWei('2')
            })
            const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
            const diff = newBlance.minus(oldBlance)
            assert.equal(diff,0)
          })
    
    8.5 还没上线的话,不能上传视频
    it('还没上线,不能上传视频',async()=>{
        
            try{
              await course.methods.addVideo('video的hash')
                        .send({
                          from:accounts[0],
                          gas:'5000000'
                        })
              assert.ok(false)
            }catch(e){
                console.log(e)
              assert.equal(e.name,'o')
            }
          })
    
    
    
    8.6 不能重复购买
      it('不能重复购买',async()=>{
        try{
          await course.methods.buy().send({
            from:accounts[2],
            value:web3.utils.toWei('2')
          })
          assert.ok(false)
    
        }catch(e){
          console.log(e.name)
          assert.equal(e.name,'RuntimeError')
    
        }
    
      })
    
    8.7 课程必须是众筹价格
      it('课程必须是众筹价格',async()=>{
        try{
          await course.methods.buy().send({
            from:accounts[4],
            value:web3.utils.toWei('3')
          })
          assert.ok(false)
    
        }catch(e){
          assert.equal(e.name,'RuntimeError')
    
        }
    
      })
    
    8.8 众筹上线后,钱到账
      
      it('众筹上线后,钱到账',async()=>{
        const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
    
        // 8 众筹家是2  买4次就上线
        await course.methods.buy().send({
          from:accounts[4],
          value:web3.utils.toWei('2')
        })
        await course.methods.buy().send({
          from:accounts[5],
          value:web3.utils.toWei('2')
        })
        const count = await course.methods.count().call()
        const isOnline = await course.methods.isOnline().call()
        assert.equal(count,4)
        assert.ok(isOnline)
        const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
        const diff = newBlance.minus(oldBlance)
        assert.equal(diff,web3.utils.toWei('8'))
      })
    
    8.9 课程必须是线上的价格
       it('课程必须是线上的价格',async()=>{
        try{
          await course.methods.buy().send({
            from:accounts[6],
            value:web3.utils.toWei('2')
          })
          assert.ok(false)
    
        }catch(e){
          assert.equal(e.name,'RuntimeError')
        }
    
      })
    
     it('课程必须是线上的价格2',async()=>{
        // try{
          await course.methods.buy().send({
            from:accounts[6],
            value:web3.utils.toWei('4')
          })
          const count = await course.methods.count().call()
          assert.equal(count,5)
    
        // }catch(e){
        //   assert.equal(e.name,'RuntimeError')
        // }
      })
    
    
    8.10 上线之后购买 有分成收益
      it('上线之后购买 有分成收益',async()=>{
        // try{
          // ceo的约
        const oldCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
        // 课程创建者
        const oldOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
    
          await course.methods.buy().send({
            from:accounts[7],
            value:web3.utils.toWei('4')
          })
          const newCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
          const newOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
    
          const diffCeo = newCeoBlance.minus(oldCeoBlance)
          const diffOwner = newOwnerBlance.minus(oldOwnerBlance)
          assert.equal(diffCeo, web3.utils.toWei('0.4'))
          assert.equal(diffOwner, web3.utils.toWei('3.6'))
        // }catch(e){
        //   assert.equal(e.name,'RuntimeError')
        // }
      })
    
    8.11 上线之后,可以上传视频
    it('上线之后,可以上传视频',async()=>{
        
          await course.methods.addVideo('video的hash')
                    .send({
                      from:accounts[0],
                      gas:'5000000'
                    })
          const video = await  course.methods.video().call()
          assert.equal(video,'video的hash')
      })
    
    8.12 完整测试代码
    const path = require('path');
    const assert = require('assert');
    const Web3 = require('web3')
    const ganache = require('ganache-cli')
    const BigNumber = require('bignumber.js')
    const web3 = new Web3(ganache.provider())
    // 引入合约的json
    const CourseList = require(path.resolve(__dirname, '../src/compiled/CourseList.json'))
    const Course = require(path.resolve(__dirname, '../src/compiled/Course.json'))
    
    
    // 定义几个全局变量,所有测试都需要
    let accounts
    // 实例
    let courseList
    let course
    
    describe('测试课程的智能', () => {
    
        before(async () => {
            // 测试前的数据初始化
            accounts = await web3.eth.getAccounts()
    
            console.log(accounts)
            // 1. 虚拟部署一个合约
            courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
                .deploy({ data: CourseList.bytecode })
                .send({
                    // 最后一个是创建者——重点
                    from: accounts[9],
                    gas: '5000000'
                })
    
        })
    
        it('合约部署成功', () => {
            assert.ok(courseList.options.address)
        })
    
        // it('测试添加课程', async () => {
        //     const oldaddress = await courseList.methods.getCourse().call()
        //     assert.equal(oldaddress.length, 0)
        //     await courseList.methods.createCourse(
        //         '蜗牛的React课程'
        //     )
        //         .send({
        //             from: accounts[0],
        //             gas: '5000000'
        //         })
        //     const address = await courseList.methods.getCourse().call()
        //     assert.equal(address.length, 1)
        //     console.log(address)
    
        // })
    
        // it("添加课程的属性", async () => {
        //     const [address] = await courseList.methods.getCourse().call()
        //     // 添加的课程合约的地址
        //     course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
        //     const name = await course.methods.name().call()
        //     assert.equal(name, '蜗牛的React课程')
        // })
        it('测试添加课程', async () => {
            const oldaddress = await courseList.methods.getCourse().call()
            assert.equal(oldaddress.length, 0)
            await courseList.methods.createCourse(
                '蜗牛的React课程',
                "React+redux+reactrouter4开发招聘app",
                web3.utils.toWei('8'),
                // 众筹价格
                web3.utils.toWei('2'),
                web3.utils.toWei('4'),
                "图片的hash"
            )
                .send({
                    from: accounts[0],
                    gas: '5000000'
                })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length, 1)
    
        })
        it("添加课程的属性", async () => {
            const [address] = await courseList.methods.getCourse().call()
            // 添加的课程合约的地址
            course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
            const name = await course.methods.name().call()
            const content = await course.methods.content().call()
            const target = await course.methods.target().call()
            const fundingPrice = await course.methods.fundingPrice().call()
            const price = await course.methods.price().call()
            const img = await course.methods.img().call()
            const count = await course.methods.count().call()
            const isOnline = await course.methods.isOnline().call()
            assert.equal(name, '蜗牛的React课程')
            assert.equal(content, 'React+redux+reactrouter4开发招聘app')
            assert.equal(target, web3.utils.toWei('8'))
            assert.equal(fundingPrice, web3.utils.toWei('2'))
            assert.equal(price, web3.utils.toWei('4'))
            assert.equal(img, "图片的hash")
            assert.ok(!isOnline)
            assert.equal(count, 0)
        })
    
    
        //删除功能
        // it("只能ceo能删", async () => {
        //     await courseList.methods.createCourse(
        //         '蜗牛的Vue课程'
        //     )
        //         .send({
        //             from: accounts[0],
        //             gas: '5000000'
        //         })
        //     const address = await courseList.methods.getCourse().call()
        //     assert.equal(address.length, 2)
    
        //     await courseList.methods.removeCourse(0).send({
        //         from: accounts[9],
        //         gas: '5000000'
        //     })
        //     const address1 = await courseList.methods.getCourse().call()
        //     console.log(address1)
        //     assert.equal(address1.length, 1)
    
        // })
        it("只能ceo能删", async ()=>{
            await courseList.methods.createCourse(
              '蜗牛的Vue课程',
              'vue也是个好框架,简单好上手',
              web3.utils.toWei('8'),
              // 众筹价格
              web3.utils.toWei('2'),
              web3.utils.toWei('4'),
              "图片的hash1"   
              )
                  .send({
                    from:accounts[0],
                    gas:'5000000'
                  })
            const address = await courseList.methods.getCourse().call()
            assert.equal(address.length,2)
        })
    
        it('判断是不是ceo', async () => {
            const isCeo1 = await courseList.methods.isCeo().call({
                from: accounts[9]
            })
            const isCeo2 = await courseList.methods.isCeo().call({
                from: accounts[1]
            })
            assert.ok(isCeo1)
            assert.ok(!isCeo2)
        })
    
        it('金钱转换',()=>{
            assert.equal(web3.utils.toWei('2'),'2000000000000000000')
          })
    
          it('课程购买',async()=>{
            await course.methods.buy().send({
              from:accounts[2],
              value:web3.utils.toWei('2')
            })
            const value = await course.methods.users(accounts[2]).call()
            const count = await course.methods.count().call()
            assert.equal(value,web3.utils.toWei('2'))
            assert.equal(count,1)
    
            // 输出value及users+
            console.log("钱是:")
            console.log(value)
            // console.log("uers是:")
    
            
            // 用户role的判断
            const detail = await course.methods.getDetail().call({from:accounts[0]})
            assert.equal(detail[9],0)
        
            // 课程
            console.log(detail)
            const detail2 = await course.methods.getDetail().call({from:accounts[2]})
            assert.equal(detail2[9],1)
        
            const detail3 = await course.methods.getDetail().call({from:accounts[5]})
            assert.equal(detail3[9],2)
          })
    
          it('还没上线,购买的课不入账',async()=>{
            const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
            await course.methods.buy().send({
              from:accounts[3],
              value:web3.utils.toWei('2')
            })
            const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
            const diff = newBlance.minus(oldBlance)
            assert.equal(diff,0)
          })
    
          it('还没上线,不能上传视频',async()=>{
        
            try{
              await course.methods.addVideo('video的hash')
                        .send({
                          from:accounts[0],
                          gas:'5000000'
                        })
              assert.ok(false)
            }catch(e){
                console.log(e)
              assert.equal(e.name,'o')
            }
          })
          it('不能重复购买',async()=>{
            try{
              await course.methods.buy().send({
                from:accounts[2],
                value:web3.utils.toWei('2')
              })
              assert.ok(false)
        
            }catch(e){
              console.log(e.name)
              assert.equal(e.name,'RuntimeError')
        
            }
        
          })
          it('课程必须是众筹价格',async()=>{
            try{
              await course.methods.buy().send({
                from:accounts[4],
                value:web3.utils.toWei('3')
              })
              assert.ok(false)
        
            }catch(e){
              assert.equal(e.name,'RuntimeError')
        
            }
        
          })
          
          it('众筹上线后,钱到账',async()=>{
            const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
        
            // 8 众筹家是2  买4次就上线
            await course.methods.buy().send({
              from:accounts[4],
              value:web3.utils.toWei('2')
            })
            await course.methods.buy().send({
              from:accounts[5],
              value:web3.utils.toWei('2')
            })
            const count = await course.methods.count().call()
            const isOnline = await course.methods.isOnline().call()
            assert.equal(count,4)
            assert.ok(isOnline)
            const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
            const diff = newBlance.minus(oldBlance)
            assert.equal(diff,web3.utils.toWei('8'))
          })
          it('课程必须是线上的价格',async()=>{
            try{
              await course.methods.buy().send({
                from:accounts[6],
                value:web3.utils.toWei('2')
              })
              assert.ok(false)
        
            }catch(e){
              assert.equal(e.name,'RuntimeError')
            }
        
          })
          it('课程必须是线上的价格2',async()=>{
            // try{
              await course.methods.buy().send({
                from:accounts[6],
                value:web3.utils.toWei('4')
              })
              const count = await course.methods.count().call()
              assert.equal(count,5)
        
            // }catch(e){
            //   assert.equal(e.name,'RuntimeError')
            // }
          })
          it('上线之后购买 有分成收益',async()=>{
            // try{
              // ceo的约
            const oldCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
            // 课程创建者
            const oldOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
        
              await course.methods.buy().send({
                from:accounts[7],
                value:web3.utils.toWei('4')
              })
              const newCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
              const newOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
        
              const diffCeo = newCeoBlance.minus(oldCeoBlance)
              const diffOwner = newOwnerBlance.minus(oldOwnerBlance)
              assert.equal(diffCeo, web3.utils.toWei('0.4'))
              assert.equal(diffOwner, web3.utils.toWei('3.6'))
            // }catch(e){
            //   assert.equal(e.name,'RuntimeError')
            // }
          })
        
          it('上线之后,可以上传视频',async()=>{
            
              await course.methods.addVideo('video的hash')
                        .send({
                          from:accounts[0],
                          gas:'5000000'
                        })
              const video = await  course.methods.video().call()
              assert.equal(video,'video的hash')
          })
    
    })
    

    END

  • 相关阅读:
    149. Max Points on a Line(js)
    148. Sort List(js)
    147. Insertion Sort List(js)
    146. LRU Cache(js)
    145. Binary Tree Postorder Traversal(js)
    144. Binary Tree Preorder Traversal(js)
    143. Reorder List(js)
    142. Linked List Cycle II(js)
    141. Linked List Cycle(js)
    140. Word Break II(js)
  • 原文地址:https://www.cnblogs.com/oneapple/p/13288040.html
Copyright © 2011-2022 走看看