Search code examples
javascriptfunctionasync-awaitweb3js

How to create web3 contract method calls using dynamic variables


I am trying to create a function that will allow me to pass in variables such as contract function names, and send()/call(), based on dynamic variables passed into the parent 'blockchainCall' function.

So far what I've found only seems to invoke the function using a string, but if you see the original example, that's not what I'm trying to do. There are multiple elements chained in the await call so I'm unsure what approach to take here. Any ideas?

async function blockchainCall(contract, action, method, val) {
        let Method = method(val);
        let Action = action();

        await contract.methods.Method.Action.then((value) => {              
            return value;           
        })          
            .catch((error) => {             
            return error;           
        });


        /* original example */
        await contract.methods.ownerOf(val).call( {from: account[0], value: price} ).then((value) => {              
            return value;           
        })          
            .catch((error) => {             
            return error;           
        });
    }

Solution

  • You can access the methods with their string signatures as items of associative array of the JS contract instance.

    The blockchainCall() function can return a promise that resolves into the returned value.

    pragma solidity ^0.8;
    
    contract MyContract {
        function foo() external {}
    
        function ownerof(uint256 tokenId) external pure returns (address) {
            return address(0x123);
        }
    }
    
    function blockchainCall(contract, action, method, val) {
        return new Promise((resolve, reject) => {
            contract.methods[method](val)[action]().then((value) => {
                resolve(value);
            }).catch((error) => {
                reject(error);
            });
        });
    }
    
    const owner = await blockchainCall2(contract, "call", "ownerof(uint256)", 1);
    console.log(owner);