How to authenticate / signin with Portis and Torus wallets

I’m trying to integrate Torus and Portis wallets, but with both I get:

Uncaught (in promise) TypeError: MWeb3 is not a constructor
    at MoralisTorusProvider._callee$ (Login.vue?013f:112)
    at tryCatch (runtime.js?89b8:63)
    at Generator.invoke [as _invoke] (runtime.js?89b8:293)
    at Generator.eval [as next] (runtime.js?89b8:118)
    at asyncGeneratorStep (asyncToGenerator.js?c973:3)
    at _next (asyncToGenerator.js?c973:25)

What am I missing? Should I import web3 myself when using a different wallet?
I’m running localhost, could that be an issue?

<script>
import { Moralis } from 'src/boot/moralis'
import Torus from '@toruslabs/torus-embed'

export default {
  setup() {
    const connectTorus = async () => {
      class MoralisTorusProvider {
        torus = new Torus({buttonPosition: 'bottom-left'})
        async activate() {
          this.provider = await this.torus.init(
            {
              enableLogging: true,
              network: {
                host: process.env.VUE_ETH_NETWORK_RPC,
                networkName: "Ethereum - Rinkeby",
                chainId: 4,
                blockExplorer: process.env.VUE_ETH_NETWORK_EXPLORER,
                ticker: 'ETH',
                tickerName: 'ETH',
              },
            })
          await this.torus.login()
          const MWeb3 = typeof Web3 === 'function' ? Web3 : window.Web3
          this.web3 = new MWeb3(this.torus.provider)
          this.isActivated = true
          return this.web3
        }
      }

      Moralis.Web3.enable = async () => {
        const web3Provider = new MoralisTorusProvider()
        const web3 = await web3Provider.activate()
        return web3
      }
      window.web3 = await Moralis.Web3.enable()
  }
}

turned out I had to import Web3 myself, missed that because I was previously using Moralis.Web3.

But how do you use Moralis.Web3.authenticate() to log in or sign up a Portis user?
Moralis.Web3.authenticate pops up metamask…
Torus the same, I’m able to connect with Torus but don’t see how to connect it to a Moralis.User.
Docs don’t mention authenticate or signup with a custom wallet:

https://docs.moralis.io/moralis-server/users/crypto-login#custom-wallet-login

@Yomoo @cryptokid @malik would really appreciate some input here to tackle this issue.
I’ve tried to connect a different wallet provider, Portis and Torus basically work the same way as I understand, overriding the web3 provider. That works fine, but how to sign up and log in with this wallet? Moralis.Web3.authenticate is opening up metamask.

    const connectPortis = async () => {
      class MoralisPortisProvider {
        async activate() {
          this.provider = portis.provider;
          portis.showPortis()
          const MWeb3 = typeof Web3 === 'function' ? Web3 : window.web3;
          this.web3 = new MWeb3(this.provider)
          this.isActivated = true;
          return this.web3;
        }
      }

      // overwrite web3 provider
      Moralis.Web3.enable = async () => {
        const web3Provider = new MoralisPortisProvider()
        const web3 = await web3Provider.activate()
        return web3
      }

      window.web3 = await Moralis.Web3.enable()

     // this pops up metamask?
      await Moralis.Web3.authenticate(
        { provider: portis.provider, signingMessage: signMessage.value }
      ). then((user) => {
        console.log('Portis user', user)
      })

Not sure if it helps, you could try Moralis.authenticate to see if it is a difference.

yeah tried that, it’s the same, was also wondering what the difference is…
There’s an example for Torus in the docs, but nothing mentioned about authentication.

I believe there’s an issue with MoralisInjectedProvider in Moralis. I provide the portis.provider to options and it works up to MoralisInjectedProvider where suddenly the provider returned is metamask. Hard to debug but following the steps in moralis.js code this is what I could see.

@malik @Yomoo @cryptokid @ivan

after debugging found the culprit at line 4468 in moralis.js:

function _getWeb3FromBrowser() {
  _getWeb3FromBrowser = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
    var _window$web;

    var MWeb3, provider, ethereum, web3;
    return _regenerator.default.wrap(function (_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            MWeb3 = typeof _web.default === 'function' ? _web.default : window.Web3;
            provider = (_window$web = window.web3) === null || _window$web === void 0 ? void 0 : _window$web.currentProvider;
            ethereum = window.ethereum;

            // IF REMOVE REMOVE provider.isTrust PORTIS AUTHENTICATION WORKS!
            if (!(provider !== null && provider !== void 0)) {
           // if (!(provider !== null && provider !== void 0 && provider.isTrust)) {
               _context3.next = 5;
              break;
            }

            return _context3.abrupt("return", new MWeb3(provider));

          // SHOULD NOT ARRIVE HERE
          case 5:
            if (!ethereum) {
              _context3.next = 10;
              break;
            }

            web3 = new MWeb3(ethereum);
            _context3.next = 9;
            return ethereum.enable();

          case 9:
            return _context3.abrupt("return", web3);


provider.isTrust prevents my custom web3 provider from being used in authenticate and causes it to default to window.ethereum instead of window.web3.

I’ve made a simplified setup modifying https://github.com/MoralisWeb3/demo-apps/tree/main/walletconnect to use portis. Works:

Code that works: (note that I add portis.provider.isTrust = true)

async function portisLogin() {
  const portis = new Portis('xxxxx', 'rinkeby')
  try {
      class MoralisPortisProvider {
        async activate() {
          this.provider = portis.provider;
          const MWeb3 = typeof Web3 === 'function' ? Web3 : window.web3;
          this.web3 = new MWeb3(this.provider)
          this.isActivated = true;
          return this.web3;
        }
      }

      // Global Moralis object overwritten
      Moralis.Web3.enable = async () => {
        const web3Provider = new MoralisPortisProvider()
        return await web3Provider.activate()
      };
      window.web3 = await Moralis.enable()
      portis.provider.isTrust = true // NEED TO ADD THIS!!
      const user = await Moralis.authenticate({ provider: portis.provider})
  } catch (error) {
    console.log('authenticate failed', error);
  }
  renderApp();
}

:sweat_smile:

3 Likes

Oh my goodness, You are a real mage :mage:
We are now looking into this, thank you so much for your help. We really appreciate it :raised_hands:

1 Like

new Portis(‘xxxxx’, ‘rinkeby’) what is marked as xxxx here/what needs to be replaced

It is the Dapp ID the Portis Provides.

You can find more info about it over here -
https://docs.portis.io/#/quick-start?id=🚀-quick-start

Hope this helps. :smiley: