nodejs使用web3js开发以太坊

本文介绍了如何使用Node.js和Web3.js库在以太坊Ropsten测试网上进行操作,包括创建账户、查询ETH余额、转账、合约代币余额查询及交易。详细步骤涵盖安装依赖、注册Infura节点、执行交易等,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

安装web3 tx


npm install web3 --save
npm install ethereumjs-tx  --save

注册节点

infura官网

eth余额查询、转账

service/ethService.js


const Web3 = require('web3')
const Tx = require('ethereumjs-tx').Transaction

var web3
if (typeof web3 !== 'undefined') {
	web3 = new Web3(web3.currentProvider);
} else {
	// set the provider you want from Web3.providers
	web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/v3/...."));
}
//创建账户
function create(){
	let acc = web3.eth.accounts.create()
	return acc
}
//获取gas价格
async function getGasPrice(){
	let price
	await web3.eth.getGasPrice().then((res) => {
		price = res
	})
	return price
}
//查询账户余额
async function balance(account){
	let balance
	await web3.eth.getBalance(account).then((res) => {
		balance = web3.utils.fromWei(res, 'ether')
	})
	return balance
}
//交易eth
async function tran(fromAdd, to, num, limit, privatekey){
	let gasPrice = await getGasPrice();
	console.log(gasPrice)
	let hash;
	await web3.eth.getTransactionCount(fromAdd, (err,txcount)=>{
		if(err){
			console.log(err)
		} else{
			const txObject = {
				nonce: web3.utils.toHex(txcount),
				to: to,
				value: web3.utils.toHex(web3.utils.toWei(num, 'ether')),
				gasLimit: web3.utils.toHex(limit),
				gasPrice: web3.utils.toHex(gasPrice)
			}
			console.log(txObject)
			// 签署交易
			const tx = new Tx(txObject, {
				chain: 'ropsten',
				hardfork: 'petersburg'
			})
			tx.sign(Buffer.from(privatekey.substring(2),'hex'))
			const serializedTx = tx.serialize()
			const raw = '0x' + serializedTx.toString('hex')
			// 广播交易
			
			web3.eth.sendSignedTransaction(raw , (err, txHash) => {
				if (!err){
					hash = txHash
				}else{
					console.log(err);
				}
			})
		}
	})
	return hash
}
module.exports = {
	create,
	getGasPrice,
	balance,
	tran
}

合约代币余额查询、交易

安装 solc fs(直接拷贝合约abi可省略此步骤)


//版本和合约版本一致
npm install --save solc@0.4.17
npm install --save fs

service/conService.js


const ethService = require('./ethService.js')
const Tx = require('ethereumjs-tx').Transaction
const fs = require('fs')
const solc = require('solc')
var web3 = ethService.web3

//编译合约
var source = fs.readFileSync("./contract/contract.sol", "utf8");
var compile = solc.compile(source, 1);
// var bytecode = compile.contracts[':TetherToken'].bytecode;
//获取abi 不在本地编译合约的,可直接拷贝合约abi在此赋值
var abi = compile.contracts[':TetherToken'].interface;
abi = JSON.parse(abi)
//合约实例
var conAdd = '0x785859EdD69cFE827c216233eAb714834E40E7ea'
var contract = new web3.eth.Contract(abi, conAdd)

//代币余额
async function balance(account) {
	let balance
	await contract.methods.balanceOf(account).call().then((res) =>{
		balance = web3.utils.fromWei(res, 'MWEI')
	})
	return balance
}

async function tran(from,to, num,limit, priKey) {
	let gasPrice = await ethService.getGasPrice();
	let hash;
	await web3.eth.getTransactionCount(from, (err,txcount)=>{
		if(err){
			console.log(err)
		} else{
			const txObject = {
				nonce: web3.utils.toHex(txcount),
				to: conAdd,
				gasLimit: web3.utils.toHex(limit),
				gasPrice: web3.utils.toHex(gasPrice*2),
				data: contract.methods.transfer(to, web3.utils.toWei(num, 'MWEI')).encodeABI()
			}// console.log(txObject)
			// 签署交易
			const tx = new Tx(txObject, {
				chain: 'ropsten',
				hardfork: 'petersburg'
			})
			tx.sign(Buffer.from(priKey.substring(2),'hex'))
			const serializedTx = tx.serialize()
			const raw = '0x' + serializedTx.toString('hex')
			// 广播交易
			web3.eth.sendSignedTransaction(raw , (err, txHash) => {
				if (!err){
					hash = txHash
					console.log("success:" + txHash)
					return hash
				}else{
					console.log(err);
				}
			})
		}
	})
}

module.exports = {
	balance,
	tran
}

合约源码 contract/contract.sol (直接拷贝合约abi可省略此步骤)


pragma solidity ^0.4.17;
/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        assert(c / a == b);
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
} 


contract Ownable {
    
    address public owner;

    function Ownable() public {
        owner = msg.sender;
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address newOwner) public onlyOwner {
        if (newOwner != address(0)) {
            owner = newOwner;
        }
    }

}

contract ERC20 {
    uint public _totalSupply;
    function totalSupply() public constant returns (uint);
    function balanceOf(address who) public constant returns (uint);
    function transfer(address to, uint value) public;
    
    function approve(address spender, uint value) public;
    function transferFrom(address from, address to, uint value) public;
    function allowance(address owner, address spender) public constant returns (uint);
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}


contract TetherToken is Ownable, ERC20 {
    
    using SafeMath for uint;
    
    string public name;
    string public symbol;
    uint public decimals;
    uint public basisPointsRate = 0;
    uint public maximumFee = 0;
    uint public constant MAX_UINT = 2**256 - 1;
    
    mapping (address => uint) public balances;
    mapping (address => mapping (address => uint)) public allowed;
   
    event Issue(uint amount);
    event Redeem(uint amount);

    function TetherToken (uint _initialSupply, string _name) public {
        _totalSupply = _initialSupply * 10**6;
        name = _name;
        symbol = _name;
        decimals = 6;
        balances[owner] = _totalSupply;
    }
    
    /**
    * @dev Fix for the ERC20 short address attack.
    */
    modifier onlyPayloadSize(uint size) {
        require(!(msg.data.length < size + 4));
        _;
    }
    
    function totalSupply() public constant returns (uint) {
        
        return _totalSupply;
    }
    
    function balanceOf(address _owner) public constant returns (uint balance) {
        return balances[_owner];
    }
    
    function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
        uint fee = (_value.mul(basisPointsRate)).div(10000);
        if (fee > maximumFee) {
            fee = maximumFee;
        }
        uint sendAmount = _value.sub(fee);
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(sendAmount);
        if (fee > 0) {
            balances[owner] = balances[owner].add(fee);
            Transfer(msg.sender, owner, fee);
        }
        Transfer(msg.sender, _to, sendAmount);
    }

    function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {

        require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));

        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
    }
    
    function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) {
        var _allowance = allowed[_from][msg.sender];
        
        uint fee = (_value.mul(basisPointsRate)).div(10000);
        if (fee > maximumFee) {
            fee = maximumFee;
        }
        if (_allowance < MAX_UINT) {
            allowed[_from][msg.sender] = _allowance.sub(_value);
        }
        uint sendAmount = _value.sub(fee);
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(sendAmount);
        if (fee > 0) {
            balances[owner] = balances[owner].add(fee);
            Transfer(_from, owner, fee);
        }
        Transfer(_from, _to, sendAmount);
    }

    function allowance(address _owner, address _spender) public constant returns (uint remaining) {
        return allowed[_owner][_spender];
    }
    
    function issue(uint amount) public onlyOwner {
        require(_totalSupply + amount > _totalSupply);
        require(balances[owner] + amount > balances[owner]);

        balances[owner] += amount;
        _totalSupply += amount;
        Issue(amount);
    }

    function redeem(uint amount) public onlyOwner {
        require(_totalSupply >= amount);
        require(balances[owner] >= amount);

        _totalSupply -= amount;
        balances[owner] -= amount;
        Redeem(amount);
    }

}

测试 controller/eth.js


const router = require('koa-router')()
const ethService = require('../service/ethService.js')
const conService = require('../service/conService.js')
router.prefix('/eth')

//创建账户
router.get('/create', async (ctx, next) => {
	let acc = ethService.create()
	ctx.body = acc
})

//获取gas价格
router.get('/gasPrice', async (ctx, next) => {
	let price = await ethService.getGasPrice()
	console.log(ethService.web3.utils.fromWei(price, 'gwei'))
	ctx.body = price
})

//查询账户余额
router.get('/balance', async (ctx, next) => {
	let balance = await ethService.balance('0x118234e32f67ad526B31Ad696f6533179a8cB42b')
	console.log(balance)
	ctx.body = balance
})

//交易
router.get('/tran', async (ctx, next) => {
	let hash = await ethService.tran('fromAdd', 'toAdd'
	,"1" ,"21000" ,'from账户私钥privatekey')
	console.log(hash)
	ctx.body = hash
})

//合约余额
router.get('/conBalance', async (ctx, next) => {
	let valance = await conService.balance('账户add')
	console.log(valance)
	ctx.body = valance
})

//合约代币交易
router.get('/conTran', async (ctx, next) => {
	let hash = await conService.tran('fromAdd','toAdd', '100','200000', 'from账户私钥privatekey')
	console.log(hash)
	ctx.body = hash
})

module.exports = router


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

bug的搬运工

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

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

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

打赏作者

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

抵扣说明:

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

余额充值