Search code examples
javascriptcommonjs

Can export a class, but can not export a functions in JS


I use different tech stacks for a current project and some things learn on the fly. I am not confident with different JS standards and their use cases. At this moment I have TypeError: chain.getSwapChainContractInstance is not a function which is a valid and exported function.

It is exported in a common for the project way via exports.getSwapChainContractInstance = function() { /* the rest of the code */}.

The module class is imported like this:

const chain = require('../models/chain/chain');
const { SwapToken, SwapChainV2 } = require('../models/chain/chain');

The whole code of the module is:

const { ethers } = require("ethers");
const config = require('config');

class Contract {
    constructor() {}

    getWalletWithProvider(privateKey, nodeUrl) {
        let provider = new ethers.providers.JsonRpcProvider(nodeUrl)
        let walletWithProvider = new ethers.Wallet(privateKey, provider);
        return walletWithProvider;
    }
}

class SwapToken extends Contract {

    constructor(privateKey, nodeUrl, contractAddress) {
        super();
        console.log(`${JSON.stringify(privateKey)}, ${JSON.stringify(nodeUrl)}, ${JSON.stringify(contractAddress)}`)
        let swapTokenAbiJson = [
            "function balanceOf(address owner) public view virtual override returns (uint256)",
        ];
        this.signerInstance = this.getWalletWithProvider(privateKey, nodeUrl);
        this.swapTokenContract = new ethers.Contract(
            contractAddress, 
            swapTokenAbiJson, 
            this.signerInstance
        );
    }

    async balanceOf(address) {
        return await this.swapTokenContract.balanceOf(address);
    }
}

class SwapChainV2 extends Contract {

    constructor(privateKey, nodeUrl, contractAddress) {
        super();
        let swapChainAbiJson = [
            "function registerUser(address user) public override",
            "function getUsers() public view override returns (address[] memory)",
            "function getMatches(address userFirst, address userSecond) external view override returns ((address,uint,address,uint,bool,bool)[])"
        ];
        this.signerInstance = this.getWalletWithProvider(privateKey, nodeUrl);
        this.swapChainContract = new ethers.Contract(
            contractAddress, 
            swapChainAbiJson, 
            this.signerInstance
        );
        
    }

    async getMatches(userFirstAddress, userSecondAddress) {
        return await this.swapChainContract.getMatches(userFirstAddress, userSecondAddress);
    }

    async getUsers() {
        return await this.swapChainContract.getUsers();
    }
}

/**
 * FIXME: by some reason I can not import it and use in the usual way 
 */
exports.getSwapChainContractInstance = function() {
    let nodeUrl = `http://${config.get("chain").host}:${config.get("chain").port}`;
    let privateKey = config.get("chain").privateKey;
    let swapChainAddress = config.get("chain").swapChainV2Address;

    return new SwapChainV2(privateKey, nodeUrl, swapChainAddress);
}

/**
 * FIXME: by some reason I can not import it and use in the usual way 
 */
exports.getSwapValueContractInstance = function() {
    let nodeUrl = `http://${config.get("chain").host}:${config.get("chain").port}`;
    let privateKey = config.get("chain").privateKey;
    let swapTokenAddress = config.get("chain").swapTokenAddress;

    return new SwapToken(privateKey, nodeUrl, swapTokenAddress);
}

module.exports = { SwapToken, SwapChainV2 }

Solution

  • In a CommonJS module, the value of exports is an object that is exported. By default it is an empty object.

    First you mutate the object to add a function to it.

    exports.getSwapChainContractInstance = function()
    

    Then you mutate it again to add a second function to it.

    exports.getSwapValueContractInstance = function() {
    

    Then you replace the whole object with a new one which exports the classes.

    module.exports = { SwapToken, SwapChainV2 }
    

    The new object you are exporting doesn't have the two function you assigned to the old object.


    Pick one method for setting your exports:

    • Mutate the object four times to add the four properties
    • Replace the object once with a single new object that already has all four properties