In einer web3 JS dApp (z. B. mit Metamask),
wenn ich nur die Adresse eines Vertrags und den Methodennamen kenne , wie kann ich diese Methode aufrufen?
ABI kenne ich nicht.
Ich poste hier eine richtige Antwort - danke an @smarx und andere von SO, die mir geholfen haben, zu dieser Lösung zu führen.
Dies ist möglich, wenn Sie die Methodensignatur (einschließlich der Typen der Parameter) kennen , aber nicht nur den Namen. – @smart
So implementiert beispielsweise ein ERC20 - konformer Token-Vertrag eine balanceOf()
Methode.
Die Signatur dieser Methode sieht so aus (siehe unten, wie man sie erhält):
var abi = [{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
Holen Sie sich jetzt die Vertragsadresse der Token, an denen Sie interessiert sind.
Als Beispiel gibt es im Ropsten -Netzwerk einen Panda-Token-Vertrag unter 0x45135b8ED5f52528175CCC6D7add2228779eDeE0 (spenden Sie Ropsten ETH hier , um einige Panda-Token zu erhalten), damit Sie Ihr Panda-Token-Guthaben sehen können mit dem folgenden Code (zusätzlich zur obigen abi-Zeile):
var tokenContractAddress = "0x45135b8ED5f52528175CCC6D7add2228779eDeE0"
var contract = web3.eth.contract( abi ).at( tokenContractAddress )
var account
web3.eth.getAccounts( (err, ok) => account = ok[0] )
// wait for account to be set ...
contract.balanceOf( account, function(err,ok) { console.log(err,ok.c[0]) } )
balanceOf()
SignaturUm die Signatur dieser Methode zu erhalten, ging ich einfach zu Remix und fügte Folgendes als Vertrag ein (nachdem ich die Funktionsdefinition aus der ERC20-Definition erhalten hatte ):
contract ERC20 {
function balanceOf(address _owner) constant returns (uint balance);
}
Gehen Sie dann zu Compile > Details > INTERFACE - ABI (Copy)
Wenn Sie die ABI oder den Bytecode nicht kennen (wenn Sie also den Vertragscode nicht haben), können Sie keine Transaktion(en) oder Aufruf(e) senden.
Aber wenn Sie es wissen, tun Sie es in web3js 1.0.0-beta einfach:
contractInstance.methods.getBalance().call(address, function(result){
//do something with the variable
});
Oder für eine Transaktion:
contractInstance.methods.setBalance(address).send({from: someone}, function(hash){
//dosomething
});
Für Kommentare bearbeiten: So erstellen Sie die ContractInstance
if (contractInstance == null || contractInstance == 'undefined') {
console.log("Making a new contract instance");
var code = fs.readFileSync(solidityFile).toString();
// Compile the contract code
var compiledCode = solc.compile(code);
//Generate the ABI
abi = JSON.parse(compiledCode.contracts[':NAMEOFYOUCONTRACT'].interface);
contractInstance = new web3.eth.Contract(abi, contractAddress);
console.log("Contract instance created successfully");
contractInstance
den Beispielcode in Ihrer Antwort? kann es ohne die ABI erstellt werden?Bitte beachten Sie, dass die Länge der Argumente, die die Funktion benötigt, bekannt sein muss. Argumente ist eine Liste der Datenstrukturen, die die Funktion benötigt. zum Beispiel: ["Adresse","bool"]
Wenn Sie sich über den Typ nicht sicher sind, verwenden Sie "int"
const genericABIGenerator = (
args,
function_name,
returnType = "int"
) => {
return [
{
inputs: args.map((value, index) => ({
name: `arg${index}`,
type: value ?? "int",
})),
name: function_name,
outputs: [
{
name: "output",
type: returnType,
},
],
stateMutability: "view",
type: "function",
},
];
};
Codeausführung
const contract = new client.eth.Contract(
genericABIGenerator(inputTypeList, function_name, outputType),
contractAddress
);
const result = await contract.methods[function_name](...args).call();
Benutzer19510