此为历史版本和 IPFS 入口查阅区,回到作品页
ericet
IPFS 指纹 这是什么

作品指纹

【科学家养成日记#2】转移代币

ericet
·

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

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

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();

运行结果:


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

CC BY-NC-ND 2.0 授权