web3.js简单学习(二)官方投票合约的编译(脚本),部署(脚本),js代码简单调用合约

1、合约代码
  • SimpleAuction.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.0;

contract SimpleAuction {

    address payable public beneficiary;
    uint public auctionEnd;
    address public highestBidder;
    uint public highestBid;
    mapping(address => uint) pendingReturns;
    bool ended;

    // 变更触发的事件
    event HighestBidIncreased(address bidder, uint amount);
    event AuctionEnded(address winner, uint amount);

    constructor(uint _biddingTime,address payable _beneficiary) {
        beneficiary = _beneficiary;
        auctionEnd = block.timestamp + _biddingTime;
    }



    function bid() public payable {
        require(block.timestamp <= auctionEnd);
        // 如果出价不够高,返还你的钱
        require(msg.value > highestBid);
        if (highestBid != 0) {
            pendingReturns[highestBidder] += highestBid;
        }
        highestBidder = msg.sender;
        highestBid = msg.value;
        emit HighestBidIncreased(msg.sender, msg.value);
    }

    /// 取回出价(当该出价已被超越)
    function withdraw() public returns (bool) {
        uint amount = pendingReturns[msg.sender];
        if (amount > 0) {
            pendingReturns[msg.sender] = 0;
            if (!payable(msg.sender).send(amount)) {
                // 这里不需抛出异常,只需重置未付款
                pendingReturns[msg.sender] = amount;
                return false;
            }
        }
        return true;
    }
    /// 结束拍卖,并把最高的出价发送给受益人
    function auctionEnded() public {
        // 1. 条件
        require(block.timestamp >= auctionEnd, "Auction not yet ended.");
        require(!ended, "auctionEnd has already been called.");
        // 2. 生效
        ended = true;
        emit AuctionEnded(highestBidder, highestBid);
        // 3. 交互
        beneficiary.transfer(highestBid);
    }
}

2、合约编译

编译脚本:Compiler.js


const fs = require('fs');
const solc = require('solc');
const { Utils } = require('./utils/utils');

class SOLCompiler {
    constructor(path, fileName) {
        this.pathFile = `${path}/${fileName}`;
        this.config = {
            language: 'Solidity',
            sources: {
            },
            settings: { // 自定义编译输出的格式。以下选择输出全部结果。
                outputSelection: {
                    '*': {
                        '*': ['*']
                    }
                }
            },
        };
        this.fileName = fileName;
    }

    async writeFile(confData) {
        return new Promise((resolve, reject) => {
            fs.writeFile(`${this.fileName}.json`, confData, (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(true);
                }
            });
        });
    }

    async compile() {
        try {
            const content = await Utils.readFile(this.pathFile);
            if (!content) {
                console.log('文件读取出错');
                return;
            }
            this.config.sources[this.fileName] = {
                content: content
            };

            // 编译得到结果
            const compiledOutStr = solc.compile(JSON.stringify(this.config));
            const compiledData = JSON.parse(compiledOutStr);

            const confData = {
                abi: {},
                bytecode: ''
            };

            // output 为json对象,根据json结构保存对应的abi和bytecode
            for (let contractName in compiledData.contracts[this.fileName]) {
                confData.abi = compiledData.contracts[this.fileName][contractName].abi;
                confData.bytecode = compiledData.contracts[this.fileName][contractName].evm.bytecode.object;
            }

            // console.log(confData);

            if (this.writeFile(JSON.stringify(confData))) {
                console.log(`compile file: ${this.fileName} is success!`);
            }
        } catch (e) {
            console.log(e.message);
        }
    }
}

if (process.argv.length > 2) {
    const pathFile = process.argv[2];
    
    const pathSplit = pathFile.split('/');
    const fileName = pathSplit[pathSplit.length - 1];
    const fileNameSplit = fileName.split('.');
    const fileExt = fileNameSplit[fileNameSplit.length - 1];
    if (fileExt.toLowerCase() != 'sol') {
        console.log('请输入正确的文件名');
        return;
    }
    const newPath = pathFile.substring(0, pathFile.length - fileName.length - 1);
    console.log(newPath, fileName);
    const cc = new SOLCompiler(newPath, fileName);

    cc.compile();
    // process.exit(0);
} else {
    console.log('请输入正确的命令行格式');
}

  • 在命令行执行命令
#第一个是编译脚本的位置 ,
#第二个是 .sol 需要编译的源文件的位置
#(因为在文件中使用了自动获取参数的形式,所以需要在命令行指定)

node ./scrips/Compile.js SimpleAuction.sol

3、合约部署
  • 部署脚本:deploy_02.js

const Web3 = require('web3');
const fs = require('fs');

const { Console } = require('console');

const web3 = new Web3('http://192.168.75.129:8545');

//通过命令行模式获取文件名作为参数
const fileNameSource_01 = process.argv.splice(2);
const fileNameSource = fileNameSource_01[0];

class Deploy {
    async readFile(filePath) {
        return new Promise((resolve, reject) => {
            fs.readFile(filePath, (err, content) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(content);
                }
            });
        });
    }

    async deploy(filePath) {
        const fileContent = await this.readFile(filePath);
        // const fileContent = fs.readFileSync(filePath);
        if (fileContent) {
            const ballotData = JSON.parse(fileContent);
            let funDeploy = async () => {
                try {
                    const accounts = await web3.eth.getAccounts();
                    const account = accounts[0];
                    console.log(account);

                    const addr = "0x4e8fe7e83628121a3757ea2f69e8f9cb3aae7123";
                    const v = 200;
                    const deployContract = new web3.eth.Contract(ballotData.abi);
            
                    const payLaod = {
                        data: ballotData.bytecode,
                        arguments: [1000,"0x8f4e1b9f8bfa09b4d4466a2a34237d454b9a2812"]
                    };
                    let parameters = {
                        from: account,
                        gas: web3.utils.toHex(5000000),
                        gasPrice: web3.utils.toHex(web3.utils.toWei('30', 'gwei'))
                    };

                    const result = await deployContract.deploy(payLaod).send(parameters, (err, txHash) => {
                        if (!err) {
                            console.log('Transaction Hash', txHash);
                        } else {
                            console.log(err.message);
                        }
                    });
                    console.log('successfully! address : ' + result.options.address);

                    return result;
                } catch (e) {
                    console.log(e.message);
                }
            };

            await funDeploy();
        }
    }
}
const filesplitName = fileNameSource.split('.');
const solc_name = filesplitName[filesplitName.length - 1];
if(solc_name.toLowerCase() != 'json'){
    Console.log("请输入正确的后缀文件名json");
    return;
}else{
    new Deploy().deploy(fileNameSource);

}

// new Deploy().deploy("./Faucet.out.json");
//new Deploy().deploy(fileNameSource);

  • 在命令行执行命令
#第一个是部署脚本的位置 ,
#第二个是 编译过后得到的 .json 文件的位置
#(因为在文件中使用了自动获取参数的形式,所以需要在命令行指定)

 node scripts/deploy_02.js compiled/SimPleAuction.sol.json

在这里插入图片描述

4、调用合约

js代码:


/**
 * 调用拍卖合约
 * 部署后得到的合约hashaddr:// 0xA33636e9A5fBBD0Ab72dA8022bC3557C0406217d
 */

//  引入web3模块
const Web3 = require('web3');
const web3 = new Web3("http://192.168.75.129:8545");

class constracatSimPleAuction{

    async constructEg(){
        const accounts = await web3.eth.getAccounts();
        const _from = accounts[0];
        // 创建合约实例
        const abi = [{"inputs":[{"internalType":"uint256","name":"_biddingTime","type":"uint256"},{"internalType":"address payable","name":"_beneficiary","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AuctionEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"HighestBidIncreased","type":"event"},{"inputs":[],"name":"auctionEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionEnded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"highestBid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"highestBidder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}];
        
        //新版本解锁的方式需要用下面这种方式web3.eth.personal.unlockAccount(地址,密码,解锁时间,回调函数)
        web3.eth.personal.unlockAccount(_from,'123456',3600,(err,res)=>{
            if(err){
                console.log("Err: ",err);
            }else{
                console.log("Result:",res);

                // methodTest(abi, address) {
				//交易地址(部署合约返回的):0x8F2093824F3B74f8C0f13cBffcF73B72e1EFF82E
                    const contractInstance = new web3.eth.Contract(abi, "0x8F2093824F3B74f8C0f13cBffcF73B72e1EFF82E");
            		//调用合约的bid()方法,send()方法是web3自带的,on后面是固定写法
                    contractInstance.methods.bid().send({
                    //bid需要的参数
                        from: _from,
                        value:1000
                    }).on('transactionHash', (hash) => {
                        console.log(hash);
                    }).on('confirmation', (confirmationNumber, receipt) => {
                    }).on('receipt', (receipt) => {
                        console.log(receipt); //查询这里可以得到结果
                    }).on('error', console.error);
                // }
            }
        });

        // const methed_01 = await contractInstance.bid();
        // const methed_02 = await contractInstance.auctionEnded();
        // const myEvent = contractInstance.HighestBidIncreased()

        
    }
     
}
new constracatSimPleAuction().constructEg();

在geth控制台开启挖矿就可以了

#开启挖矿,得到一个块就停止
  miner.start(1);admin.sleepBlocks(1);miner.stop()

运行调用合约代码返回的结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雲小妖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值