继上文【科学家养成日记#1】读取钱包代币数量, 这次的作业是转移钱包里面的代币

如果是转移链的原生代币,比如以太链的ETH,BSC链的BNB,构造的tx的data可为空。不是原生的代币就需要通过ERC20的合约构造一个data。所以转移ERC20代币的费用会比原生代币的高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const Web3 = require('web3');
const erc20Abi = require('./ABI/erc20.json');
const rpcUrl = 'https://data-seed-prebsc-1-s1.binance.org:8545';
const rpcWeb3 = new Web3(new Web3.providers.HttpProvider(rpcUrl));
let web3 = rpcWeb3;

/**
* 通过小数点多少位,转换对应的数据
* @param {*} tokenDecimals 小数点位数
* @returns 相对应的位数名
*/
function getWeiName(tokenDecimals = 18) {
tokenDecimals = Number(tokenDecimals);
let weiName = 'ether';
switch (tokenDecimals) {
case 3:
weiName = "Kwei";
break;
case 6:
weiName = 'mwei';
break;
case 9:
weiName = 'gwei';
break;
case 12:
weiName = 'microether ';
break;
case 15:
weiName = 'milliether';
break;
case 18:
weiName = 'ether';
break;
default:
weiName = 'ether';
break;

}
return weiName;
}

/**
* 获得钱包原生代币余额
* @param {*} address 钱包地址
* @returns 钱包原生代币数量
*/
const getBnbBalance = (address) => {
return new Promise(async (resolve, reject) => {
let result = await web3.eth.getBalance(address);
if (result) {
let balance = web3.utils.fromWei(result, getWeiName());
resolve(balance);
} else {
reject("Getting Bnb Balance error.");
}
})
}

/**
* 获得ERC20代币余额
* @param {*} tokenAddress 代币的合约
* @param {*} address 钱包地址
* @returns ERC20代币余额
*/
const getTokenBalance = (tokenAddress, address) => {
return new Promise(async (resolve, reject) => {
let tokenContract = new web3.eth.Contract(erc20Abi, tokenAddress);
let result = await tokenContract.methods.balanceOf(address).call();
let decimals = await tokenContract.methods.decimals().call();
let weiName = getWeiName(decimals);
let tokenBalance = web3.utils.fromWei(result, weiName);
let symbol = await tokenContract.methods.symbol().call();
resolve(`${tokenBalance} ${symbol}`);
})

}

/**
* 转移代币
* @param {*} from 来源钱包
* @param {*} to 目标钱包
* @param {*} amount 数量
* @param {*} input 构造的数据
*/
const transfer = async (from, to, amount, input) => {
let gasPrice = await web3.eth.getGasPrice();
let gasLimit = 420000;
let nounce = await web3.eth.getTransactionCount(from);
let nbnb = web3.utils.toWei((amount).toString(10), 'ether');
let tx = {
nounce,
gasPrice,
gasLimit,
to,
value: nbnb,
data: input
}
web3.eth.accounts.signTransaction(tx, process.env.PRIVATE_KEY).then(signed => {
web3.eth.sendSignedTransaction(signed.rawTransaction).on('receipt', console.log)
})

}

/**
* 转移ERC20代币
*/
async function transferErc20() {
let account = web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY);
let from = account.address;
let toWallet = "0xF5FD98884ba506B8F0a4afC856063f1fF42a30C9";
let tokenAddress = '0xed24fc36d5ee211ea25a80239fb8c4cfd80f12ee';//BUSD
let balance = await getTokenBalance(tokenAddress, from);
let amount = 0.1;
const tokenContract = new web3.eth.Contract(erc20Abi, tokenAddress);
const input = tokenContract.methods.transfer(toWallet, web3.utils.toWei((amount).toString(), 'ether')).encodeABI();
if (parseFloat(balance) > amount) {
console.log(`Transferring ${amount} BUSD from ${from} to ${toWallet}.`)
transfer(from, tokenAddress, 0, input);
} else {
console.log('Insufficient balance to transfer!');
}
}

/**
* 转移原生代币
*/
async function transferBnB() {
let account = web3.eth.accounts.privateKeyToAccount(process.env.PRIVATE_KEY);
let from = account.address;
let balance = await getBnbBalance(from);
let to = "0xF5FD98884ba506B8F0a4afC856063f1fF42a30C9";
let amount = 0.01;
if (balance > amount) {
console.log(`Transferring ${amount} BNB from ${from} to ${to}.`)
transfer(from, to, amount, '');
} else {
console.log('Insufficient balance to transfer!');
}
}

//在源代码的基础上,调用代币的transfer功能转移代币(比如WBNB)
transferErc20();
transferBnB();

运行结果:
image.png

源代码: https://github.com/ericet/kexuejia