Solidity
從 node.js 中現有的松露合約呼叫函式
這可能是一個非常容易解決的問題,但我正在為我的 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(),因為它會在返回實例之前驗證程式碼是否存在於指定地址。