在使用web3js操作以太坊时,主要包含3个步骤:
1、构造交易参数
2、将交易信息使用私钥签名
3、发送签名交易
var web3;
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
web3 = new Web3(new Web3.providers.HttpProvider(RPC_URL));
}
{
from: // 交易发起方地址
to: // 交易目标地址
value: // 交易eth数量(当调用合约时,此处可以为0)
data: // 扩展字段(当调用合约时,此处为合约的方法以及参数)
gasPrice: // 手续费单价
gasLimit: // 手续费上限
}
web3.eth.accounts.signTransaction('你的交易参数对象', 'yourPrivateKey').then(tx => {
console.log('Result: ', tx);
var raw = tx.rawTransaction;
}
web3.eth.sendSignedTransaction('上面的raw').on('receipt', res => {
console.log('操作成功');
}).on('error', err => {
console.log('操作异常');
});
var txData = {
from: // 交易发起方地址
to: // 交易目标地址
value: // 交易eth数量(当调用合约时,此处可以为0)
data: // 扩展字段(当调用合约时,此处为合约的方法以及参数)
gasPrice: // 手续费单价
gasLimit: // 手续费上限
}
web3.eth.accounts.signTransaction(txData , 'yourPrivateKey').then(tx => {
console.log('Result: ', tx);
var raw = tx.rawTransaction;
web3.eth.sendSignedTransaction(raw).on('receipt', res => {
console.log('操作成功');
}).on('error', err => {
console.log('操作异常');
});
}
交易参数 | 转账ETH | 调用合约 |
---|---|---|
from | 这个毫无疑问,交易发起方即操作人的钱包地址 | - |
to | 目标账户 | 合约地址 |
value | ETH数量 | 0x00 |
data | 视为扩展字段,可有可无 | 方法名称+参数列表 |
gasPrice | 手续费单价 | - |
gasLimit | 手续费上限 | - |
// 操作eth
web3.eth.estimateGas({
from:yourAccountAddr,
to: toAddress,
data: '0x00'
}).then(res => {
console.log(res);
}
// 操作合约
web3.eth.estimateGas({
from: yourAccountAddr,
to: token.options.address,
data: funcAbi (该参数后面说明)
}).then(res => {
console.log(res);
}
// abi可以使用remix编译源码后获得
var abi = [];
var token = new web3.eth.Contract(abi, 'yourContractAddress');
// 可以直接获得地址和私钥
var account = web3.eth.accounts.create();
// 如果需要使用钱包的方式操作,加密获得的是一个json格式的钱包
var store = web3.eth.accounts.encrypt(account.privateKey, 'yourPassword');
// 通过钱包和密码生成私钥
account = web3.eth.accounts.decrypt(store, 'yourPassword');
var key = account.privateKey;
// 通过私钥生成账户信息,如果发生错误,说明私钥不正确
account = web3.eth.accounts.privateKeyToAccount(key);
var funcAbi = token.methods.transfer(toAddress, web3.utils.toWei(num, 'ether')).encodeABI();
// 用上面的transfer进行举例
var tokenNum = web3.utils.toWei(num, 'ether');
// '0x70a08231' : 合约方法名称的hex编码
// substring(2) : 将hex编码的前缀(0x)拿掉
// addPreZero : 参数前补0,已达到参数长度一致
var funcAbi = '0x70a08231' + addPreZero(toAddress).substring(2) + addPreZero(tokenNum).substring(2);
var addPreZero = (num) => {
var t = (num+'').length,
s = '';
for(var i=0; i<64-t; i++){
s += '0';
}
return s+num;
}
// 引入js
// 创建对象
var tx = new ethereumjs.Tx(null, 'networkId');
tx.nonce = ''; // 账户的 transactionCount
tx.gasPrice = web3.utils.hexToNumber(web3.utils.toWei('price', 'gwei'));
tx.gasLimit = 100000; // 此处因为是离线签名,所以无法动态获取gasLimit
// 获取私钥buffer对象
var keyBuffer = ethereumjs.Buffer.Buffer.from('yourKey', 'hex');
// 如果是ETH
tx.value = (new web3.utils.BN(web3.utils.toWei(num, 'ether'))).toString('hex');
tx.to = targetAddress;
// 如果是合约
tx.data = funcAbi;
tx.value = '0x00';
tx.to = token.options.address;
tx.sign(keyBuffer);
var raw = '0x' + tx.serialize().toString('hex');
// 然后发送签名交易即可
// res 为估算的gasLimit
var pay = new web3.utils.BN(res);
var balance = new web3.utils.BN(web3.utils.toWei(ethBalance, 'ether'));
// 比较大小 < = >
// -1 0 1
if (balance.cmp(pay) === -1) {
console.log('手续费不足,请核实');
return;
}
// 减;add 为 加
var subRes = balance.sub(pay);
// 乘
var mulRes = balance.mul(pay);
// 获取账户ETH余额
web3.eth.getBalance(defaultAccount).then(res => {
var ethBalance = web3.utils.fromWei(res, 'ether');
});
// 获取账户代币余额
token.methods.balanceOf(address).call().then(res => {
var vccBalance = web3.utils.fromWei(res, 'ether');
});
// 合约字节码和ABI均可以使用remix编译源码获得,args为构造函数参数列表
var contract = new api.web3.eth.Contract(JSON.parse(abi));
var transactionData = contract.deploy({
data: '合约字节码',
arguments: eval("(" + args + ")")
}).encodeABI();
var options = {
from: address,
data: transactionData,
gasPrice: web3.utils.toWei(gasPrice, 'gwei'),
gasLimit: '程序估算的值'
}
// 签名,发送交易
web3.eth.accounts.signTransaction(options, 'yourPrivateKey')....