一、创建一个新的项目
新建一个Express 框架的项目
二、安装web3
在此附上,web3 在github的地址:
https://github.com/ethereum/web3.js/tree/2.x
执行安装web3
[root@192 node]# cd jiaocheng #node.js项目根目录
[root@192 jiaocheng]# npm install web3
三、引入现有的库
[root@192 jiaocheng]# npm install bip39 ethereumjs-wallet ethereumjs-util ethers ethereumjs-tx --save
var Web3 = require('web3');
var bip39 = require('bip39');
var hdkey = require('ethereumjs-wallet/hdkey');
var util = require('ethereumjs-util');
var ethers = require('ethers');
var EthereumTx = require('ethereumjs-tx').Transaction;
四、创建带助记词的钱包
if(req.query.fn === "walletNew"){ //创建钱包
//1、生成助记词
let mnemonic = bip39.generateMnemonic();
//2、将助记词转成seed
let seed = bip39.mnemonicToSeedSync(mnemonic);
//3、通过hdkey 将seed生成HD Wallet
let hdWallet = hdkey.fromMasterSeed(seed);
//4、生成钱包中在m/44'/60'/0'/0/0路径的keypair
let key = hdWallet.derivePath("m/44'/60'/0'/0/0");
//5、从keypair中获取私钥
let privateKey = util.bufferToHex(key._hdkey._privateKey);
//6、从keypair中获取公钥
let publicKey = util.bufferToHex(key._hdkey._publicKey);
//7、使用keypair中的公钥生成地址
let address = util.pubToAddress(publicKey,true);
address = util.toChecksumAddress(address.toString('hex'));
//8、生成keystore
let keystore = web3.eth.accounts.encrypt(privateKey,req.query.password);
res.json({
code: 1,
message: 'OK',
data:{
mnemonic:mnemonic,
privateKey:privateKey,
publicKey:publicKey,
address:address,
keystore:keystore,
user_id:req.query.user_id
}});
五、助记词方式导入钱包
if(req.query.type === "mnemonic") { //助记词方式导入
//2、将助记词转成seed
let seed = bip39.mnemonicToSeedSync(req.query.mnemonic);
//3、通过hdkey 将seed生成HD Wallet
let hdWallet = hdkey.fromMasterSeed(seed);
//4、生成钱包中在m/44'/60'/0'/0/0路径的keypair
let key = hdWallet.derivePath("m/44'/60'/0'/0/0");
//5、从keypair中获取私钥
let privateKey = util.bufferToHex(key._hdkey._privateKey);
//6、从keypair中获取公钥
let publicKey = util.bufferToHex(key._hdkey._publicKey);
//7、使用keypair中的公钥生成地址
let address = util.pubToAddress(publicKey, true);
address = util.toChecksumAddress(address.toString('hex'));
//8、生成keystore
let keystore = web3.eth.accounts.encrypt(privateKey, req.query.password);
res.json({
code: 1,
message: 'OK',
data: {
mnemonic: req.query.mnemonic,
privateKey: privateKey,
publicKey: publicKey,
address: address,
keystore: keystore,
user_id: req.query.user_id
}
});
六、私钥方式导入钱包
else if(req.query.type === "privateKey"){ //私钥方式导入
//获取钱包对象
wallet = new ethers.Wallet(req.query.privateKey);
//生成keystore
let keystore = web3.eth.accounts.encrypt(req.query.privateKey, req.query.password);
res.json({
code: 1,
message: 'OK',
data: {
privateKey: wallet.signingKey.keyPair.privateKey,
publicKey: wallet.signingKey.keyPair.compressedPublicKey,
address: wallet.signingKey.address,
keystore: keystore,
user_id: req.query.user_id
}
});
七、store对象方式导入钱包
else if(req.query.type === "keystore"){ //store对象方式导入
wallet = web3.eth.accounts.decrypt(req.query.keystore,req.query.password);
wallet = new ethers.Wallet(wallet.privateKey);
res.json({
code: 1,
message: 'OK',
data: {
privateKey: wallet.signingKey.keyPair.privateKey,
publicKey: wallet.signingKey.keyPair.compressedPublicKey,
address: wallet.signingKey.address,
keystore: req.query.keystore,
user_id: req.query.user_id
}
});
八、获取指定类型的余额
else if(req.query.fn === "getBalance"){ //获取指定类型的余额
if(req.query.type === "ETH"){
web3.eth.getBalance(req.query.address).then(function(balance){
res.json({
code: 1,
message: 'OK',
data: {balance: web3.utils.fromWei(balance,'ether')}
});
});
}else if(req.query.type === "SEA"){
let abi = JSON.parse(fs.readFileSync('./routes/seaToken.abi','utf8'));
con = new web3.eth.Contract(abi,conaddress);
con.methods.getBalance().call({from: req.query.address}).then(function(balance){
res.json({
code: 1,
message: 'OK',
data: {balance: web3.utils.fromWei(balance,'mwei')}
});
});
九、ETH链上转账操作
if(req.query.type === "ETH"){
//先做交易签名
//先获取当前付款账号的交易数量(nonce)
web3.eth.getTransactionCount(req.query.address_from,web3.eth.defaultBlock.pending).then(function(nonce){
//将私钥,转换为16进制
let privateKey = Buffer.from(req.query.privateKey.substr(2),'hex');
//设置交易数据
let txData = {
// nonce每次++,以免覆盖之前pending中的交易
nonce: web3.utils.toHex(nonce++),
// 设置gasLimit和gasPrice
gasLimit: web3.utils.toHex(req.query.gas),
gasPrice: web3.utils.toHex(web3.utils.toWei(req.query.gasprice,'ether')),
// 要转账的哪个账号
to: req.query.address_to,
// 从哪个账号转
from: req.query.address_from,
// 以太币转账金额
value: web3.utils.toHex(web3.utils.toWei(req.query.money,'ether')),
data: ''
}
const tx = new EthereumTx(txData);
//用私钥签署交易
tx.sign(privateKey);
//序列化
const serializedTx = tx.serialize().toString('hex');
//发送已签名交易
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'),function(error,hash){
if(!error){
res.json({
code: 1,
message: 'OK',
data: {hash: hash}
});
} else{
res.json({
code: -2,
message: error,
data: {}
});
}
});
});
十、代币链上发送交易操作
else if(req.query.type === "SEA"){
//web.eth方法
// 补齐64位,不够前面用0补齐
function addPreZero(num){
var t = (num+'').length,
s = '';
for(var i=0; i<64-t; i++){
s += '0';
}
return s+num;
}
web3.eth.getTransactionCount(req.query.address_from, web3.eth.defaultBlock.pending).then(function(nonce){
//将私钥,转换为16进制
//let privateKey = Buffer.from(req.query.privateKey.substr(2),'hex'); //扣除用户eth
let privateKey = Buffer.from("调用者私钥",'hex'); //扣除平台eth
//设置交易数据
let txData = {
// nonce每次++,以免覆盖之前pending中的交易
nonce: web3.utils.toHex(nonce++),
// 设置gasLimit和gasPrice
gasLimit: web3.utils.toHex(req.query.gas),
gasPrice: web3.utils.toHex(web3.utils.toWei(req.query.gasprice,'ether')),
// 这里是代币合约地址
to: conaddress,
// 从哪个账号转
from: req.query.address_from,
// 以太币转账金额
value: '0x00',
// data的组成,由:0x + 要调用的合约方法的function signature + 要传递的方法参数,每个参数都为64位(对transfer来说,第一个是接收人的地址去掉0x,第二个是代币数量的16进制表示,去掉前面0x,然后补齐为64位)
data: '0xa5cfc11f' + addPreZero(req.query.address_from.substr(2)) +addPreZero(req.query.address_to.substr(2))+ addPreZero(web3.utils.toHex(web3.utils.toWei(req.query.money,'mwei')).substr(2))
}
const tx = new EthereumTx(txData);
//用私钥签署交易
tx.sign(privateKey);
//序列化
const serializedTx = tx.serialize().toString('hex');
//发送已签名交易
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'),function(error,hash){
if(!error){
res.json({
code: 1,
message: 'OK',
data: {hash: hash}
});
}else{
res.json({
code: -2,
message: error.toString(),
data: {}
});
}
});
});