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

调用智能合约函数时出现TypeError: Cannot read property 'apply' of undefined错误

Fixing "TypeError: Cannot read property 'apply' of undefined at Provider.sendAsync" in Truffle Contract + Angular

I’ve run into this exact error before working with Truffle contracts in Angular, so let’s break down what’s causing it and how to fix it step by step.

What’s Causing This Error?

This error pops up when your Truffle contract instance tries to call the sendAsync method on an Ethereum provider that’s either undefined or doesn’t support the old sendAsync interface (like modern MetaMask, which uses EIP-1193’s request method instead). Looking at your CarService.ts code, the most likely culprits are missing provider initialization or version mismatches between your dependencies.

Step-by-Step Fixes

1. Ensure Your Web3 Service Provides a Valid Provider

First, check your Web3Service to make sure it’s correctly fetching the Ethereum provider (e.g., from MetaMask). Modern MetaMask no longer injects web3.currentProvider by default—you need to use window.ethereum instead. Here’s how to update your Web3Service:

// web3.service.ts
import { Injectable } from '@angular/core';
import Web3 from 'web3';

@Injectable()
export class Web3Service {
  web3: Web3 | undefined;

  constructor() {
    this.initWeb3();
  }

  async initWeb3() {
    // Check if MetaMask or another provider is available
    if (window.ethereum) {
      try {
        // Request account access if needed
        await window.ethereum.request({ method: 'eth_requestAccounts' });
        this.web3 = new Web3(window.ethereum);
      } catch (error) {
        console.error('User denied account access', error);
      }
    } else if (window.web3) {
      // Fallback for older dApp browsers
      this.web3 = new Web3(window.web3.currentProvider);
    } else {
      console.error('No Ethereum provider found');
    }
  }

  async ensureWeb3IsReady(): Promise<Web3> {
    if (!this.web3) {
      await this.initWeb3();
    }
    return this.web3 as Web3;
  }
}

2. Properly Initialize Your Truffle Contract with the Provider

In your CarServiceService, don’t try to set the provider synchronously in the constructor—wait for the Web3 provider to be ready first. Use async/await with the ensureWeb3IsReady method from your Web3Service:

// CarService.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { fromPromise } from 'rxjs/observable/fromPromise';
import { Web3Service } from './web3.service';
import contract from '@truffle/contract'; // Use maintained @truffle/contract package
const carArtifacts = require('../../../build/contracts/Car.json');

@Injectable()
export class CarServiceService {
  private CarContract: any;

  constructor(private web3Service: Web3Service) {
    this.CarContract = contract(carArtifacts);
  }

  async initContract() {
    const web3 = await this.web3Service.ensureWeb3IsReady();
    // Set the provider for the contract
    this.CarContract.setProvider(web3.currentProvider);
    // Fetch the deployed contract instance
    return await this.CarContract.deployed();
  }

  // Example function to call a contract method
  getCarDetails(carId: number): Observable<any> {
    return fromPromise(this.initContract().then(async (instance: any) => {
      return await instance.getCar(carId);
    }));
  }
}

3. Switch to the Maintained Truffle Contract Package

The old truffle-contract package is deprecated—switch to @truffle/contract which supports modern EIP-1193 providers. Run these commands to update:

npm uninstall truffle-contract
npm install @truffle/contract

Update your import statement as shown in the code above to match.

4. Verify Dependency Version Compatibility

Make sure your web3 and @truffle/contract versions are compatible. As of 2024, these versions work reliably together:

  • web3: ^1.10.0
  • @truffle/contract: ^4.6.31

Check your package.json and adjust versions if needed.

Final Checks

  • Ensure MetaMask is installed and unlocked when testing your app.
  • If using a local testnet (like Ganache), confirm your provider points to the correct network URL (e.g., http://localhost:7545).

内容的提问来源于stack exchange,提问作者Sarah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:51:39