类型错误:path.resolve不是一个函数。

3
我刚刚完成了一门基于Udemy的以solc @^0.4.17、React和Next.js为基础的Ethereum智能合约课程。我觉得尝试将所有东西升级到最新版本并进行重构是一项有趣的练习。我在名为factory.js的文件中编写了以下代码,它被导入到我的主要索引文件中:
import web3 from './web3';
const path = require('path');
const fs = require('fs');

const abiPath = path.resolve('ethereum/build', 'CampaignFactory.abi');
console.log(abiPath);

const abi = fs.readFileSync(abiPath, 'utf8');
console.log(abi);

const factory = new web3.eth.Contract(
    JSON.parse(abi),
    '0x2d54559dCe0DA6C92378A916e9eE0422CEFFCD80'
);

export default factory;

在我的主索引文件中,我这样调用它:
import factory from '../ethereum/factory';
...
class CampaignIndex extends Component {
    static async getInitialProps() {
        const campaigns = await factory.methods.getDeployedCampaigns().call();

        return { campaigns };
    }
...

这是console.log的输出:
    wait  - compiling /...
    event - compiled successfully in 637 ms (1422 modules)
    /Users/sonnyparlin/Github/kickstart/ethereum/build/CampaignFactory.abi
    [
      {
        "inputs": [
          {
            "internalType": "uint256",
            "name": "minimum",
            "type": "uint256"
          }
        ],
        "name": "createCampaign",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
      },
      {
        "inputs": [
          {
            "internalType": "uint256",
            "name": "",
            "type": "uint256"
          }
        ],
        "name": "deployedCampaigns",
        "outputs": [
          {
            "internalType": "address",
            "name": "",
            "type": "address"
          }
        ],
        "stateMutability": "view",
        "type": "function"
      },
      {
        "inputs": [],
        "name": "getDeployedCampaigns",
        "outputs": [
          {
            "internalType": "address[]",
            "name": "",
            "type": "address[]"
          }
        ],
        "stateMutability": "view",
        "type": "function"
      }
    ]

控制台日志确认path.resolve()实际上正在工作,但当我通过Web浏览器访问页面时,我看到以下错误:

enter image description here

Call Stack
Module../ethereum/factory.js
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/pages/index.js (1148:1)
Module.options.factory
/_next/static/chunks/webpack.js (638:31)
__webpack_require__
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/webpack.js (37:33)
fn
/_next/static/chunks/webpack.js (307:21)
eval
webpack-internal:///./pages/index.js (9:75)
Module../pages/index.js
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/pages/index.js (1192:1)
Module.options.factory
/_next/static/chunks/webpack.js (638:31)
__webpack_require__
file:///Users/sonnyparlin/Github/kickstart/.next/static/chunks/webpack.js (37:33)
fn
/_next/static/chunks/webpack.js (307:21)
eval
node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?page=%2F&absolutePagePath=%2FUsers%2Fsonnyparlin%2FGithub%2Fkickstart%2Fpages%2Findex.js! (5:15)
eval
node_modules/next/dist/client/route-loader.js (236:50)

我的猜测是这实际上是一种版本控制或依赖关系问题,因此我也包括了我的 package.json 文件:
{
  "name": "kickstart",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha",
    "dev": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@truffle/hdwallet-provider": "^1.0.37",
    "fs-extra": "^10.0.0",
    "ganache-cli": "^6.1.8",
    "mocha": "^9.1.3",
    "next": "^12.0.3",
    "next-routes": "^1.4.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "semantic-ui-css": "^2.4.1",
    "semantic-ui-react": "^2.0.4",
    "solc": "^0.8.9",
    "web3": "^1.6.0"
  },
  "browser": {
    "fs": false,
    "path": false,
    "os": false
  }
}

我的项目文件清单:

enter image description here


你的 index.js 文件中确切的哪里在使用 factory?如果在客户端代码中使用它,那将会出现问题,因为它使用了 Node.js 的 API(pathfs)。 - juliomalves
它只被用在getInitialProps()中,我知道这是合法的。 - Sonny Parlin
不完全正确。getInitialProps 在服务器端(第一次页面加载)和客户端(客户端页面导航)上都会运行。 - juliomalves
1个回答

1
当您导入factory.js时,接下来会运行整个文件,它会看到"path"并抛出错误。
"path"用于获取合约文件的目录,而"fs"用于读取合约文件。然后使用"solc"编译器编译此代码,您可以使用此文件运行。
  node fileName.js

根据你使用solc定义的指令,这次编译将会创建一个具有"abi"属性的.json文件。到目前为止,我们与next.js没有任何关系。
然后,将其重构为一个单独的文件:
import abi from "directory/file.json"

const factory = new web3.eth.Contract(
    // pass the abi
    JSON.parse(abi),
    '0x2d54559dCe0DA6C92378A916e9eE0422CEFFCD80'
);

现在你需要将这个导入到你的Next.js项目中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接