Solidity

從 node.js 中現有的松露合約呼叫函式

  • January 29, 2020

這可能是一個非常容易解決的問題,但我正在為我的 Dapp 使用 express 設置 node.js 後端,現在我可以很好地部署新合約。

我現在需要弄清楚如何呼叫現有合約(之前在 Remix 中創建)中的函式。我有以下用於設置提供程序的語法。這至少適用於創建一個新的 Insurer:

const Web3 = require("web3");
const HDWalletProvider = require("@truffle/hdwallet-provider");

require('dotenv').config();
const provider = new HDWalletProvider(process.env.MNEMONIC, process.env.INFURA_URL);

var contract    = require("@truffle/contract");

const insurerArtifacts = require('./build/contracts/Insurer.json');
var myInsurerContract = contract(insurerArtifacts);
myInsurerContract.setProvider(provider);

const platformArtifacts = require('./build/contracts/Platform.json');
var myPlatformContract = contract(platformArtifacts);
myPlatformContract.setProvider(provider);

我進行的函式呼叫如下:

var insurerAddress = '0x...';
var myClientUIC = req.body.clientUIC;
var myClientName = req.body.clientName;
var myClientGroup = req.body.clientGroup;
var myClientNACE = req.body.clientNACE;
var myCreditLine = parseInt(req.body.creditLine);
var myCreditLineDate = parseInt(req.body.creditLineDate);
var myClientCurrency = req.body.clientCurrency;
var myClientCity = req.body.clientCity;
var myClientCountry = req.body.clientCountry;

myPlatformContract.at("0x...").methods.createClient(myClientUIC, myClientName, myClientGroup, 
   myClientNACE, insurerAddress, myCreditLine, myCreditLineDate, myClientCurrency, myClientCity, myClientCountry,
   { from:provider.getAddress() })
   .once('transactionHash', function(hash) {
       console.log("TxHash: " + hash);
   }).on('receipt', function(receipt) { console.log("receipt: " + JSON.stringify(receipt)); })
       .then(function(result) {
   }, function(error) {
       console.log(error);
   });

我得到的錯誤是:

TypeError: Cannot read property 'createClient' of undefined 

但是,createClient 是一個函式,我檢查了所有參數是否都有值。createClient 本身是否需要以不同的方式呼叫?

對於這個初學者的問題,如果您能給我任何幫助,我將不勝感激!非常感謝。菲爾

我相信您必須await在呼叫其任何方法之前返回合約實例。這就是你變得不確定的原因。

所以,你應該首先這樣做:

_instance = await myPlatformContract.at("0x...");

然後你可以繼續呼叫它的方法。把它放在一個非同步函式中,這樣你就可以使用await.

async function createAndCall() {
   console.log("instantiating contract...");

   _instance = await myPlatformContract.at(deployedAddress);

   console.log("fetching response...")

   //I'm using your original contract to test this and I know it has the 
   //insurerUIC public variable; this line is here just to show the instance
   //is now available and working:
   let response = await _instance.insurerUIC.call(); 

   console.log("Response: " + response);
}

最好的方法是創建一個保存實例的變數。所以,我通常做的是類似這樣的事情:

var _instance;
async function instantiate() {
   _instance = await myContract.at(deployedAddress);
}

然後在解決之後我只是正常呼叫函式。.methods除非您想通過其簽名呼叫函式(您現在不需要) ,否則您不需要該部分。你可以直接這樣做: _instance.functionName(params, {from:userAddress }).once(...

這裡要記住的重要一點是呼叫和事務都是非同步的,所以在做任何事情之前你需要等待響應。這也適用於 contract.at(),因為它會在返回實例之前驗證程式碼是否存在於指定地址。

引用自:https://ethereum.stackexchange.com/questions/79411