0

In my next.js app I'm initializing the SafeServiceClient like so:


import React, {useState, useEffect } from 'react';
import EthersAdapter from '@gnosis.pm/safe-ethers-lib'
import SafeServiceClient from '@gnosis.pm/safe-service-client'
import { InjectedConnector } from '@web3-react/injected-connector'
import {ethers} from 'ethers'
import { useWeb3React } from "@web3-react/core";

const txServiceUrl = 'https://safe-transaction-goerli.safe.global/';
declare let window: any;

function Comp() {

  const injected = new InjectedConnector({
    supportedChainIds: [1, 3, 4, 5, 42],
  })

  /// Local states
  const [safeService, setSafeService] = useState<any>()
  const [safes, setSafes] = useState([])

  // Hooks
  const { account, activate, deactivate } = useWeb3React();
  
  const provider = new ethers.providers.Web3Provider(window.ethereum)
  const safeOwner = provider.getSigner(0)

  const adapter = new EthersAdapter({
      ethers,
      signer: safeOwner
    })

  /** 
   *  Initialise: SafeServiceClient
   *  Fetch: Safes
   *  @issue SafeServiceClient not initialised properly
   * */ 
   useEffect(() => {        
    const fetchData = async (ownerAddress:string) => {
      const ethAdapter = adapter as EthersAdapter
      const initSafeService = new SafeServiceClient({ txServiceUrl, ethAdapter })

      // successfully returns safeService object
      console.log(initSafeService) 
      
      // returns error Cannot read properties of undefined (reading 'getEip3770Address')
      const fetchedSafes:any = await initSafeService.getSafesByOwner(ownerAddress)
      setSafes(fetchedSafes.safes)
      setSafeService(initSafeService)
    }
    if(account){
      fetchData(account)
    }
  }, [account]);



  /// Connect Metamask
  async function connect() {
    try {
    await activate(injected)//.then(() => initSafeService())
    } catch (ex) {
    console.log(ex)
    }
  }

  /// Disconnect Metamask
  async function disconnect() {
    try {
    deactivate()
    } catch (ex) {
    console.log(ex)
    }
  }

  return (
    <div>
      <button onClick={() => connect()}>
        connect
      </button>
      <button onClick={() => disconnect()}>
        disconnect
      </button>
    </div>
  );
}


export default Comp;



The console.log(initSafeService) returns the SafeServiceClient object successfully. However, the initSafeService.getSafesByOwner(ownerAddress) returns error:

enter image description here

If I rerun the useEffect (by disconnecting and reconnecting the account) the error doesn't show and safes are fetched properly.

What am I missing?

1 Answer 1

0

Sounds like an synchronization problem...

EDIT: change await because useEffect can't receive async functions...

Maybe you need to wait for the fetchData() function to finish doing it's thing?

  useEffect(() => {        
    const fetchData = async (ownerAddress:string) => {
      const ethAdapter = adapter as EthersAdapter
      const initSafeService = new SafeServiceClient({ txServiceUrl, ethAdapter })
      console.log(initSafeService)
      const fetchedSafes = await initSafeService.getSafesByOwner(ownerAddress)
      setSafes(fetchedSafes.safes)
    }
    if(account){
      setSafeOwner(account as string);
      fetchData(account).then(() => {
        // do other dependent things...
      });
    }
  }, [account]);

Just an idea, since the fetchData() function is async...

6
  • It's not possible to await within useEffect hook, you'll have to create another async function within the hook for that, and then it'll just be an endless loop of functions awaiting each other I guess. Jan 22 at 10:18
  • sorry, you're right... is setSafeOwner() async too? Is it required to be executed before the fetchData() async function?
    – prc
    Jan 24 at 9:03
  • setSafeOwner is just a react.useState hook. The error persists if I remove it. Jan 24 at 10:20
  • Maybe it would help if you could share more code...
    – prc
    Jan 24 at 11:22
  • I added a working example Jan 24 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.