You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在前端与智能合约的Payable函数交互?——请求实现调用placeBet函数的JavaScript方案

Interacting with Your Payable placeBet Smart Contract Function from the Frontend

Let's start by recalling your contract's placeBet function first—here's the snippet you shared:

function placeBet(uint8 matchID, string memory bettingType, uint8 oddForWinning) override external payable MBet { 
    require(keccak256(abi.encodePacked(bettingType)) == keccak256(abi.encodePacked("Tie")) || 
            keccak256(abi.encodePacked(bettingType)) == keccak256(abi.encodePacked("Team A")) || 
            keccak256(abi.encodePacked(bettingType)) == keccak256(abi.encodePacked("Team B")), 
            "Betting type must be 'Team A' or 'Team B' or 'Tie'"); 
    bets[msg.sender] = Bet(matchID, bettingType, oddForWinning, msg.value); 
    players.push(msg.sender); 
    string memory b = "Bet received!"; 
    emit UpdatedBet(msg.sender ,b); 
}

To interact with this payable function from the frontend, we'll use Ethers.js v6 (the latest stable version) since it's widely adopted and straightforward. Here's a complete, reusable JavaScript function that handles wallet connection, contract interaction, and error handling:

// Replace these with your actual contract details
const CONTRACT_ADDRESS = "0xYourContractAddressHere";
// Make sure your ABI includes the `placeBet` function definition
const CONTRACT_ABI = [
  // ... other contract functions/events ...
  {
    "inputs": [
      { "internalType": "uint8", "name": "matchID", "type": "uint8" },
      { "internalType": "string", "name": "bettingType", "type": "string" },
      { "internalType": "uint8", "name": "oddForWinning", "type": "uint8" }
    ],
    "name": "placeBet",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  // Include the UpdatedBet event if you want to listen for it
  {
    "anonymous": false,
    "inputs": [
      { "indexed": false, "internalType": "address", "name": "", "type": "address" },
      { "indexed": false, "internalType": "string", "name": "", "type": "string" }
    ],
    "name": "UpdatedBet",
    "type": "event"
  }
];

async function placeBetFrontend(matchID, bettingType, oddForWinning, ethAmount) {
  try {
    // Step 1: Check if MetaMask (or another wallet) is installed
    if (!window.ethereum) {
      throw new Error("Please install MetaMask or another Ethereum wallet!");
    }

    // Step 2: Connect to the user's wallet and get a signer
    await window.ethereum.request({ method: "eth_requestAccounts" });
    const provider = new ethers.BrowserProvider(window.ethereum);
    const signer = await provider.getSigner();

    // Step 3: Create a contract instance connected to the signer
    const betContract = new ethers.Contract(CONTRACT_ADDRESS, CONTRACT_ABI, signer);

    // Step 4: Convert ETH amount to wei (required for payable functions)
    const valueInWei = ethers.parseEther(ethAmount.toString());

    // Step 5: Call the payable `placeBet` function
    console.log("Sending bet transaction...");
    const tx = await betContract.placeBet(
      matchID,
      bettingType,
      oddForWinning,
      { value: valueInWei } // This is critical for payable functions!
    );

    // Step 6: Wait for the transaction to be mined and confirmed
    const receipt = await tx.wait();
    console.log("Bet successful! Transaction receipt:", receipt);

    // Optional: Listen for the UpdatedBet event to confirm the bet was processed
    betContract.on("UpdatedBet", (sender, message) => {
      console.log(`Bet confirmed from ${sender}: ${message}`);
    });

    return receipt;
  } catch (error) {
    // Handle common errors
    if (error.code === 4001) {
      console.error("User rejected the transaction.");
    } else if (error.message.includes("Betting type must be")) {
      console.error("Invalid betting type—must be 'Team A', 'Team B', or 'Tie'.");
    } else {
      console.error("Error placing bet:", error);
    }
    throw error;
  }
}

// Example usage: Place a 0.1 ETH bet on Team A for match ID 1 with odd 2
// placeBetFrontend(1, "Team A", 2, 0.1);

Key Notes for Payable Function Interaction:

  • Specify the value parameter: This is non-negotiable for payable functions—it tells the blockchain how much ETH to send along with the transaction. Always convert ETH to wei (using ethers.parseEther) since Solidity uses wei as the smallest unit.
  • Signer vs Provider: You need a Signer (not just a Provider) because we're sending a transaction that modifies the blockchain. The signer handles signing the transaction with the user's private key.
  • Error Handling: The function catches common issues like wallet rejection, invalid betting types (from the contract's require statement), and network errors.
  • ABI Requirements: Make sure your contract ABI includes the placeBet function definition—you can generate this from your Solidity code using Hardhat, Truffle, or Remix.

If you're using Web3.js instead of Ethers.js, the core logic is the same: connect the wallet, create a contract instance, and call the function with a value parameter set to the wei amount. The syntax will differ slightly, but the concepts are identical.

内容的提问来源于stack exchange,提问作者Nikola Nikitović

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:12:32