以太坊钱包余额转账代码详解,从原理到实践

 :2026-02-17 4:57    点击:25  

在区块链的世界里,以太坊作为最智能的合约平台之一,其代币(如ETH及各种ERC20代币)的转移是核心操作之一,对于开发者而言,掌握如何通过代码安全、有效地将钱包中的余额转出,是一项至关重要的技能,本文将详细介绍以太坊钱包余额转账的核心代码实现,涵盖基本原理、代码示例(以JavaScript和Solidity为例)以及关键注意事项。

核心原理:以太坊转账的本质

以太坊上的转账本质上是一次交易(Transaction),发起转账时,发送方(From账户)需要向以太坊网络广播一笔包含以下关键信息的交易:

  1. 接收方地址 (To Address):接收资产的地址。
  2. 转账金额 (Value):对于ETH,是以太为单位(1 ETH = 10^18 wei);对于ERC20代币,是代币的最小单位。
  3. 发送方签名 (Signature):使用发送方私钥对交易进行签名,证明该交易确实由发送方发起且未经篡改。
  4. Gas Limit:发送方愿意为这笔交易支付的最大计算量单位,用于限制交易执行的成本。
  5. Gas Price:发送方愿意为每个Gas单位支付的价格,决定了交易的优先级。
  6. nonce:发送方账户发起的交易序列号,用于防止重放攻击。

当矿工(或验证者)打包这笔交易时,会从中扣除相应的Gas费用(Gas Limit * Gas Price),然后将资产从发送方地址转移到接收方地址。

准备工作:环境与依赖

在编写代码之前,你需要准备以下工具和环境:

  1. 以太坊节点或Infura/Alchemy等服务:用于连接以太坊网络,Infura和Alchemy提供了便捷的RPC接口,适合开发测试。
  2. 钱包软件(如MetaMask):用于管理私钥、查看地址和测试。切记:不要在代码中硬编码私钥!
  3. 开发环境
    • Node.js:用于运行JavaScript代码。
    • 以太坊相关库
      • ethers.js随机配图
> 或 web3.js:用于与以太坊交互的JavaScript库,本文主要使用ethers.js,因其更现代且API友好。
  • solc:Solidity编译器,如果需要编译Solidity合约。
  • 测试ETH:从测试网络(如Goerli、Sepolia)获取测试ETH,用于支付Gas费用和测试转账。
  • 代码实现:以JavaScript (ethers.js) 为例

    这是最常见的情况,即从一个外部拥有账户(EOA)通过代码发送ETH或ERC20代币。

    1 发送ETH转账

    const ethers = require("ethers");
    // 1. 配置Provider(连接到以太坊网络)
    const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID"); // 替换为你的Infura ID或节点URL
    // 2. 创建Wallet(从私钥创建,实际应用中应从安全的地方获取,如硬件钱包、环境变量等)
    // 警告:不要将私钥直接写在代码中!这里仅作示例
    const privateKey = "YOUR_PRIVATE_KEY"; // 替换为发送方的私钥
    const wallet = new ethers.Wallet(privateKey, provider);
    // 3. 接收方地址
    const recipientAddress = "0xRecipientAddressHere..."; // 替换为接收方地址
    // 4. 转账金额(以ETH为单位,转换为wei)
    const amountToSend = ethers.utils.parseEther("0.01"); // 转账0.01 ETH
    // 5. 构建并发送交易
    async function sendEthTransaction() {
        try {
            // 获取当前nonce(防止交易重复)
            const nonce = await wallet.getTransactionCount();
            // 构建交易对象
            const tx = {
                to: recipientAddress,
                value: amountToSend,
                gasLimit: ethers.utils.hexlify(21000), // ETH转账通常21000 gas
                nonce: nonce,
                chainId: 5, // Goerli测试网的chainId,主网为1
            };
            // 发送交易(会返回交易哈希)
            const txResponse = await wallet.sendTransaction(tx);
            console.log("交易已发送,哈希:", txResponse.hash);
            // 等待交易被打包
            const txReceipt = await txResponse.wait();
            console.log("交易已确认,区块号:", txReceipt.blockNumber);
            console.log("余额已转出!");
        } catch (error) {
            console.error("转账失败:", error);
        }
    }
    sendEthTransaction();

    2 发送ERC20代币转账

    ERC20代币的转账不是直接调用transfer方法到接收方地址,而是调用代币合约的transfer方法,参数为接收方地址和转账金额。

    const ethers = require("ethers");
    // 1. 配置Provider和Wallet(同上)
    const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID");
    const privateKey = "YOUR_PRIVATE_KEY";
    const wallet = new ethers.Wallet(privateKey, provider);
    // 2. ERC20代币合约地址(以Goerli测试网的DAI为例)
    const tokenAddress = "0x11fE4B6AE13d2a6055C8D9cF65c22B0E383A8687"; // 替换为你要转账的代币合约地址
    // 3. 接收方地址
    const recipientAddress = "0xRecipientAddressHere...";
    // 4. 代币合约ABI(只需包含transfer方法)
    const tokenAbi = [
        "function transfer(address to, uint amount) returns (bool)",
        "function balanceOf(address account) view returns (uint)",
        "function decimals() view returns (uint8)"
    ];
    // 5. 创建代币合约实例
    const tokenContract = new ethers.Contract(tokenAddress, tokenAbi, wallet);
    // 6. 转账金额(注意代币的decimals)
    const amountToSend = ethers.utils.parseUnits("100", 18); // 假设代币有18位小数,转账100个代币
    async function sendErc20Transaction() {
        try {
            // 获取当前nonce
            const nonce = await wallet.getTransactionCount();
            // 调用代币合约的transfer方法
            const txResponse = await tokenContract.transfer(recipientAddress, amountToSend);
            console.log("代币转账交易已发送,哈希:", txResponse.hash);
            // 等待交易被打包
            const txReceipt = await txResponse.wait();
            console.log("代币转账交易已确认,区块号:", txReceipt.blockNumber);
            console.log("代币余额已转出!");
        } catch (error) {
            console.error("代币转账失败:", error);
        }
    }
    // 可选:先查询发送方代币余额
    async function checkTokenBalance() {
        const balance = await tokenContract.balanceOf(wallet.address);
        console.log(`发送方 ${wallet.address} 的代币余额:`, ethers.utils.formatUnits(balance, 18));
    }
    checkTokenBalance().then(() => sendErc20Transaction());

    Solidity 合约中的转账代码

    如果你想在智能合约内部实现余额转出(合约管理员提取资金或用户提取收益),代码会略有不同。

    1 合约接收ETH并允许提取

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    contract EtherWallet {
        address public owner;
        constructor() {
            owner = msg.sender; // 部署者成为所有者
        }
        // 接收ETH
        receive() external payable {}
        // 提取ETH到指定地址
        function withdrawEth(address payable _to, uint256 _amount) external {
            require(msg.sender == owner, "Only owner can withdraw");
            require(address(this).balance >= _amount, "Insufficient balance");
            // 转账ETH
            (bool success, ) = _to.call{value: _amount}("");
            require(success, "ETH transfer failed");
        }
        // 查询合约ETH余额
        function getBalance() external view returns (uint256) {
            return address(this).balance;
        }
    }

    2 合约内部转账ERC20代币

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
    contract TokenWallet {
        address public owner;
        constructor() {
            owner = msg.sender;
        }
        // 提取ERC20代币到指定地址
        function withdrawErc20(address _tokenAddress, address _to, uint256 _amount) external {
            require(msg.sender ==

    本文由用户投稿上传,若侵权请提供版权资料并联系删除!