reown-com / react-native-examples

React Native examples implementing Reown AppKit & WalletKit
MIT License
90 stars 33 forks source link

[bug]: WAGMI useWriteContract is unresponsive #170

Open thezaidbintariq opened 3 weeks ago

thezaidbintariq commented 3 weeks ago

Description

I want to call a function on my smart contract for which I'm using wagmi's useWriteContract hook.

The problem is the hook is not erroring out or firing the transaction. Since, there's no error in the console I'm unable to determine the problem. Attaching the code for the component below. Any help is appreciated :)

Issue Environment

Output of npx react-native info

System: OS: macOS 15.0 CPU: (8) arm64 Apple M1 Pro Memory: 257.53 MB / 16.00 GB Shell: version: "5.9" path: /bin/zsh Binaries: Node: version: 16.20.2 path: /opt/homebrew/opt/node@16/bin/node Yarn: version: 1.22.22 path: /opt/homebrew/bin/yarn npm: version: 8.19.4 path: /opt/homebrew/opt/node@16/bin/npm Watchman: version: 2024.08.05.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.15.2 path: /Users/is-005/.rbenv/shims/pod SDKs: iOS SDK: Platforms:

info React Native v0.75.3 is now available (your project is running on v0.74.5). info Changelog: https://github.com/facebook/react-native/releases/tag/v0.75.3 info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.74.5 info For more info, check out "https://reactnative.dev/docs/upgrading?os=macos"

Steps to reproduce

import React, { Suspense, useEffect, useState, useTransition } from 'react'
import { AppRegistry, View, Text, ActivityIndicator, Pressable, Button } from 'react-native'
import '@walletconnect/react-native-compat'
import { WagmiProvider, useReadContracts, useWriteContract, useAccount } from 'wagmi'
import { sepolia, mainnet } from '@wagmi/core/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { createAppKit, defaultWagmiConfig, AppKit, AppKitButton, NetworkButton } from '@reown/appkit-wagmi-react-native'
import { LPE_TOKEN_ABI, LPE_TOKEN_EXCHANGE_ABI } from './abi'
import { config } from './config'
import { RequestModal } from './RequestModel'
// 1. Get projectId at https://cloud.reown.com
const projectId = '39a38f05adaa9e35db442c0a64abdac2'

const LPE_TOKEN_CONTRACT = {
  address: '0x708638c124204e93Eb7A0EC1FC9e590AAFD305FB',
  abi: LPE_TOKEN_ABI,
} as const

const LPE_TOKEN_EXCHANGE_CONTRACT = {
  address: '0x77287A30363eC91C1719Af966A4E27C9021cF3e9',
  abi: LPE_TOKEN_EXCHANGE_ABI,
} as const

// 2. Create config
const metadata = {
  name: 'AppKit RN',
  description: 'AppKit RN Example',
  url: 'https://reown.com/appkit',
  icons: ['https://avatars.githubusercontent.com/u/179229932'],
  redirect: {
    native: 'YOUR_APP_SCHEME://',
    universal: 'YOUR_APP_UNIVERSAL_LINK.com'
  }
}

const chains = [mainnet, sepolia] as const

const wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata })

// 3. Create modal
createAppKit({
  projectId,
  wagmiConfig,
  defaultChain: sepolia,
  enableAnalytics: true
})

const queryClient = new QueryClient()

function AppContent() {
  const [isTransitionPending, startTransition] = useTransition()
  const [shouldFetch, setShouldFetch] = useState(false)

  const [requestModalVisible, setRequetsModalVisible] = useState(false);
  const { isConnected, address, status } = useAccount();

  const { writeContractAsync } =
    useWriteContract();

  const { data: contractsData } = useReadContracts({
    contracts: [
      {
        ...LPE_TOKEN_EXCHANGE_CONTRACT,
        functionName: 'totalLiquidity',
      },
      {
        ...LPE_TOKEN_EXCHANGE_CONTRACT,
        functionName: 'MAX_BUY',
      },
      {
        ...LPE_TOKEN_EXCHANGE_CONTRACT,
        functionName: 'MIN_BUY',
      },
      {
        ...LPE_TOKEN_CONTRACT,
        functionName: 'balanceOf',
        args: ["0xA1CF1cD5715415825Da4b2E5D5e6dA720B238312"],
      },
      {
        ...LPE_TOKEN_CONTRACT,
        functionName: 'name',
      },
      {
        ...LPE_TOKEN_CONTRACT,
        functionName: 'symbol',
      },
    ],
  })

  const handleFetch = () => {
    startTransition(() => {
      setShouldFetch(true)
    })
  }

  // Function to safely stringify data, handling BigInt values
  const safeStringify = (data: any): string => {
    return JSON.stringify(data, (_, value) =>
      typeof value === 'bigint' ? value.toString() : value
    )
  }

  const buyTokens = async () => {
    console.log("buyTokens");
    try {
      writeContractAsync({
        chainId: sepolia.id,
        address: LPE_TOKEN_EXCHANGE_CONTRACT.address,
        abi: LPE_TOKEN_EXCHANGE_ABI,
        functionName: 'buyTokens',
        args: [10000000000000000],
      });
    } catch (error) {
      console.log(error);
    }
  };

  const addLiquidity = async () => {
    try {
      writeContractAsync({
        chainId: sepolia.id,
        address: LPE_TOKEN_EXCHANGE_CONTRACT.address,
        abi: LPE_TOKEN_EXCHANGE_ABI,
        functionName: 'addLiquidity',
        args: ['0.01'],
      });
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    console.log("isConnected", isConnected);
  }, [isConnected]);

  useEffect(() => {
    console.log("address", address);
  }, [address]);

  useEffect(() => {
    console.log("status", status);
  }, [status]);

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <AppKitButton />
      <NetworkButton />
      <AppKit />

      <Text onPress={handleFetch}>Fetch Data</Text>
      {isTransitionPending && <ActivityIndicator />}
      {contractsData && <Text>{safeStringify(contractsData)}</Text>}
      <Pressable onPress={buyTokens} style={{ padding: 10, backgroundColor: 'lightblue', margin: 10 }}>
        <Text>buy 10 tokens</Text>
      </Pressable>
      <Pressable onPress={addLiquidity} style={{ padding: 10, backgroundColor: 'lightblue', margin: 10 }}>
        <Text>add Liquidity</Text>
      </Pressable>
    </View>
  )
}

function App() {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <Suspense fallback={<ActivityIndicator />}>
          <AppContent />
        </Suspense>
      </QueryClientProvider>
    </WagmiProvider>
  )
}

// Register the app
AppRegistry.registerComponent('main', () => App)

export default App

Snack, code example, screenshot, or link to a repository

https://github.com/thezaidbintariq/react-native-metamask

ignaciosantise commented 1 week ago

Hey @thezaidbintariq that's probably an issue with Wagmi. How are you checking that the write contract is not being fired?

const {data, isPending, isSuccess, isError, writeContract} = useWriteContract();

did you check what is returned in data, isPending, isSuccess, isError ?