首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修复"MetaMask不再注入web3“&”无法读取未定义属性(读取'toWei')“错误时使用毛毛雨构建Dapp?

如何修复"MetaMask不再注入web3“&”无法读取未定义属性(读取'toWei')“错误时使用毛毛雨构建Dapp?
EN

Ethereum用户
提问于 2022-03-13 10:23:17
回答 1查看 724关注 0票数 1

我正在尝试为彩票智能合同构建一个分散的应用程序,部署在本地的ganache ethereum网络上,但在这种情况下,我使用的是来自Truffle的毛毛雨工具。

这是智能契约,非常简单,它有pickWinner、enter和getPlayers函数。

代码语言:javascript
复制
contract Lottery {
    address public manager;
    address payable[] public players;
    uint256 index;

    constructor() payable {
        manager = msg.sender;
    }

    function enter() public payable {
        require(msg.value == .02 ether);
        players.push(payable(msg.sender));
    }

    function random() private view returns (uint256) {
        return
            uint256(
                keccak256(
                    abi.encodePacked(block.difficulty, block.timestamp, players)
                )
            );
    }

    function pickWinner() public restricted {
        index = random() % players.length;
        players[index].transfer(address(this).balance);
        players = new address payable[](0);
    }

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    function getPlayers() public view returns (address payable[] memory) {
        return players;
    }
}

我已经安装了@微雨/商店和web3模块。我还创建了一个名为contracts的文件夹与智能契约在本地Ganache网络上部署时生成的工件之间的符号链接,这是为了创建智能契约的一个实例,以及在通过毛毛雨访问智能契约时,如果更新了它的最后一个版本。我在-s ./../构建/合同中使用。

在这个项目上,我有一个index.js文件。这是在负责创建一个毛毛雨对象,并从与工件链接的源文件加载智能契约,然后有一个Redux商店来包含彩票智能契约的状态,并在应用程序的App组件中包含微流对象。

代码语言:javascript
复制
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

import { Drizzle, generateStore } from "@drizzle/store";
import Lottery from "./contracts/Lottery.json";

const options = { contracts: [Lottery] };

const drizzleStore = generateStore(options);
const drizzle = new Drizzle(options, drizzleStore);

ReactDOM.render(<App drizzle={drizzle} />, document.getElementById("root"));

那么我就有了一个App.js文件。这是在负责定义,这个组件是传递一个毛毛雨对象和毛毛雨存储从index.js文件。App组件使用它们订阅毛毛雨商店的更新。由于应用程序是模块化的,有一些子组件,为了访问和更新彩票智能契约,向其中传递drizzleState对象和毛毛雨对象。

代码语言:javascript
复制
import React, { Component } from 'react';
import './App.css';
import ViewPlayers from "./ViewPlayers";
import EnterLottery from "./EnterLottery";
import PickWinner from "./PickWinner";
import ViewDetails from "./ViewDetails";


class App extends Component {

  state = { loading: true, drizzleState: null };


async componentDidMount() {
    const { drizzle } = this.props;

    this.unsubscribe = drizzle.store.subscribe(() => {

      const drizzleState = drizzle.store.getState();
      if (drizzleState.drizzleStatus.initialized) {
        this.setState({ loading: false, drizzleState });
      }
    });
  }


compomentWillUnmount() {
    this.unsubscribe();
  }


render() {
  if (this.state.loading) return "Loading Drizzle...";
  return (

    <div className="App">

      <h2 >Lottery Contract</h2>
      <div  align="left">
      <ViewDetails
        drizzle={this.props.drizzle}
        drizzleState={this.state.drizzleState}
      />
      </div>

      <hr />

      <div  align="left">
      <ViewPlayers
        drizzle={this.props.drizzle}
        drizzleState={this.state.drizzleState}
      />
      </div>

      <hr />
      <div  align="left">
        <EnterLottery 
          drizzle={this.props.drizzle}
          drizzleState={this.state.drizzleState}
        />
        </div>
      <hr />

      <div  align="left">
        <PickWinner 
          drizzle={this.props.drizzle}
          drizzleState={this.state.drizzleState}
        />
        </div>
      <hr />

    </div>
  );
}
}

export default App;

然后,ViewPlayers、EnterLottery、PickWinner和ViewDetails子组件定义如下:

代码语言:javascript
复制
// ViewPlayers.js

import React from "react";

class ViewPlayers extends React.Component {
  
    state = { dataKey: null };

    componentDidMount() {

        const { drizzle } = this.props;
        const contract = drizzle.contracts.Lottery;

        var dataKey = contract.methods.getPlayers.cacheCall();
        console.log(contract);
        this.setState({ dataKey });
    }

    render() {
        const { Lottery } = this.props.drizzleState.contracts;
        const players = Lottery.getPlayers[this.state.dataKey];

        var rows = [];
        for (var i = 0; i < (players && players.value.length); i++) {
            rows.push(<label key={i}> <br />Player {i+1} - {players && players.value[i]} </label>);
          }

        return <p>All {players && players.value.length }  players are {rows}</p>;
    }
}

export default ViewPlayers;
代码语言:javascript
复制
// EnterLottery.js

import React from "react";

class EnterLottery extends React.Component {
  
  enter = () => {

    const { drizzle, drizzleState } = this.props;
    const contract = drizzle.contracts.Lottery;

    contract.methods.enter.cacheSend({
      from: drizzleState.accounts[0],
      value: window.web3.utils.toWei(0.2, 'ether')
    });
  };

render() {
    return (
      <div>
      <h4>Want to try your luck?</h4>
      <label>Pay 0.2 ether to enter</label> <br /><br />
        <button className='button' 
                style={{height: 40,
                        width: 150,
                        borderRadius: 10,
                        fontSize: 15}}
                onClick={this.enter}> <b>Enter</b> </button>
      </div>
    );
  }
}
export default EnterLottery;
代码语言:javascript
复制
// PickWinner.js

import React from "react";

class PickWinner extends React.Component {
  
  pick = () => {

    const { drizzle, drizzleState } = this.props;
    const contract = drizzle.contracts.Lottery;

    contract.methods.pickWinner.cacheSend({
      from: drizzleState.accounts[0]
    });
  };


render() {
    return (
      <div>
      <h4>Ready to pick a winner?</h4>
       <div><button className='button' 
                      style={{height: 40,
                              width: 150,
                              borderRadius: 10,
                              fontSize: 15}}
                    onClick={this.pick} >
                    <b>Pick Winner</b>
            </button></div>
      </div>
    );
  }
}
export default PickWinner;
代码语言:javascript
复制
// ViewDetails.js

import React from "react";

class ViewDetails extends React.Component {
  
    state = { manager: null, winningPrize: null};

    async componentDidMount() {

        const { drizzle } = this.props;
        console.log(drizzle);
        const contract = drizzle.contracts.Lottery;

        var manager = contract.methods.manager.cacheCall();
        var winningPrize = await drizzle.web3.eth.getBalance(contract.address)

        this.setState({ manager, winningPrize});
    }

    render() {
        const { drizzle } = this.props;
        const { Lottery } = this.props.drizzleState.contracts;
        const manager = Lottery.manager[this.state.manager];
        const balance = this.state.winningPrize;
        
       return (
        <p>This contract is managed by <b>{manager && manager.value}</b>.
         All players are competing to win  <b>{balance && drizzle.web3.utils.fromWei(balance,'ether')}</b> ether!</p>
        )
    }
}
export default ViewDetails;

我和Metamask有联系。

然后,当我运行npm时,网页会呈现出来,但是当我单击enter按钮时,它不会连接到Metamask。我在浏览器控制台上有一个日志:

代码语言:javascript
复制
MetaMask no longer injects web3. For details, see: https://docs.metamask.io/guide/provider-migration.html#replacing-window-web3
代码语言:javascript
复制
Uncaught TypeError: Cannot read properties of undefined (reading 'toWei')
    at EnterLottery.enter (EnterLottery.js:17:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
    at invokeGuardedCallback (react-dom.development.js:4056:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4070:1)
    at executeDispatch (react-dom.development.js:8243:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js:8275:1)
    at processDispatchQueue (react-dom.development.js:8288:1)
    at dispatchEventsForPlugins (react-dom.development.js:8299:1)
    at react-dom.development.js:8508:1

从日志中,我了解到web3注入不再受支持,所以有一种解决方案是使用window.web3.currentProvider,但我不知道如何在EnterLottery.js文件上使用它(也许我甚至应该在其他地方使用它?),我不知道在哪里实现更改才能工作。嗯,我也有一个错误的toWei方法的web3模块。

我该怎么做呢?

EN

回答 1

Ethereum用户

发布于 2022-03-13 16:58:19

使用ethereum对象,如元面罩中所述。

票数 1
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/123703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档