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. Commented Jan 22, 2023 at 10:18
  • sorry, you're right... is setSafeOwner() async too? Is it required to be executed before the fetchData() async function?
    – prc
    Commented Jan 24, 2023 at 9:03
  • setSafeOwner is just a react.useState hook. The error persists if I remove it. Commented Jan 24, 2023 at 10:20
  • Maybe it would help if you could share more code...
    – prc
    Commented Jan 24, 2023 at 11:22
  • I added a working example Commented Jan 24, 2023 at 15:48

Your Answer

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

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