Skip to content

Commit

Permalink
Added guide for Web2 devs
Browse files Browse the repository at this point in the history
  • Loading branch information
lukecd committed Aug 9, 2024
1 parent a768661 commit 56d1e7d
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 3 deletions.
1 change: 1 addition & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import nextra from "nextra";
const withNextra = nextra({
theme: "nextra-theme-docs",
themeConfig: "./theme.config.jsx",
defaultShowCopyCode: true,
});

const nextConfig = withNextra();
Expand Down
2 changes: 1 addition & 1 deletion pages/build/onchain-data/guides/_meta.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"monitor-account-balance": "Monitoring account balance"
"monitor-account-balance": "Monitor Account Balance"
}
10 changes: 10 additions & 0 deletions pages/build/programmable-data/solidity-library.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# Irys Solidity Library

This will detail how to use the Irys Solidity library to access onchain data.

It will include an overview and API ref.

Or if we end up linking perm data to smart contracts in another way, then this will document that.

Placeholder for now.
1 change: 0 additions & 1 deletion pages/build/ui/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"calling-smart-contracts": "Calling Smart Contracts",
"ui-toolkit": "UI Toolkit",
"irys-react-hooks": "Irys React Hooks",
"wagmi-hooks": "WAGMI Hooks",
"guides": "Guides",
"troubleshooting": "Troubleshooting"
}
3 changes: 2 additions & 1 deletion pages/build/ui/guides/_meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"irys-react": "npx create-react-app",
"vite": "Vite"
"vite": "Vite",
"calling-smart-contracts": "Calling Smart Contracts"
}
302 changes: 302 additions & 0 deletions pages/build/ui/guides/calling-smart-contracts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
import { Callout } from "nextra-theme-docs";
import { Tabs } from 'nextra/components'

# Calling Smart Contracts with `wagmi` and `viem`

This guide is for Web2 developers who are comfortable with React and NextJS but are new to working with smart contracts.

In Web2, calling an API involves sending HTTP requests to a server. In Web3, smart contracts replace the server, and interactions are done via transactions on the blockchain. This guide demonstrates how to call smart contract functions using two popular libraries: wagmi and viem.


## wagmi vs viem

This guide includes code examples for both [`wagmi`](https://wagmi.sh/react/getting-started) and [`viem`](https://viem.sh/).

- Approach: wagmi is a React Hooks library designed for developers who prefer using hooks. viem, is a TypeScript library focused on low-level blockchain interactions.

- Abstraction Level: wagmi provides a higher level of abstraction, making it easier to work with common tasks like connecting wallets and reading/writing to contracts using React Hooks. viem offers more granular control.

- Which to Choose?: Choose wagmi if you're building a dApp with React and want a straightforward way to manage blockchain interactions using hooks. Choose for viem if you need more control over blockchain interactions and prefer a TypeScript-first library.

## Differences Between Calling APIs and Smart Contracts

- State Changes: Unlike a Web2 API, smart contract interactions can change the blockchain's state, requiring gas fees and transaction validation.
- Immutability: Once deployed, smart contracts are immutable.
- Transaction Costs: Writing to the blockchain incurs costs, reading from the blockchain is free.

## Setup

Install `wagmi` or `viem`.

<Tabs items={['wagmi', 'viem']}>
<Tabs.Tab>
```bash
npm install wagmi ethers
```
</Tabs.Tab>
<Tabs.Tab>
```bash
npm install viem ethers
```
</Tabs.Tab>
</Tabs>

## Connecting to a Wallet

Before interacting with a smart contract, you need to connect to a user's wallet. This is similar to authenticating a user in a Web2 app.

<Tabs items={['wagmi', 'viem']}>
<Tabs.Tab>
```tsx
import { useAccount, useConnect, useDisconnect } from 'wagmi';
import { InjectedConnector } from 'wagmi/connectors/injected';

const WalletConnect = () => {
const { connect } = useConnect({
connector: new InjectedConnector(),
});
const { disconnect } = useDisconnect();
const { isConnected } = useAccount();

return (
<div>
{isConnected ? (
<button onClick={() => disconnect()}>Disconnect</button>
) : (
<button onClick={() => connect()}>Connect Wallet</button>
)}
</div>
);
};
```
</Tabs.Tab>
<Tabs.Tab>
```tsx
import { createClient, connect } from 'viem';
import { WalletConnectConnector } from 'viem/connectors/walletConnect';

const client = createClient({
connectors: [
new WalletConnectConnector({
options: {
qrcode: true,
},
}),
],
});

const WalletConnect = () => {
const [isConnected, setIsConnected] = React.useState(false);

const handleConnect = async () => {
const connector = client.getConnector('walletConnect');
await connect({ connector });
setIsConnected(true);
};

return (
<div>
{isConnected ? (
<button onClick={() => setIsConnected(false)}>Disconnect</button>
) : (
<button onClick={handleConnect}>Connect Wallet</button>
)}
</div>
);
};
```
</Tabs.Tab>
</Tabs>


## Preparing the Contract

In Web2, you might interact with a service by initializing an SDK. In Web3, you initialize a contract instance using the ABI and the contract address.

**ABI (Application Binary Interface)** is a JSON array that describes the interface of the smart contract, including its functions, events, and types. It allows your client code to understand the contract's methods and how to parse the returned data.

<Tabs items={['wagmi', 'viem']}>
<Tabs.Tab>
```tsx
import { useContract } from 'wagmi';
import { abi } from './YourContract.json'; // Replace with your contract's ABI

const contractAddress = '0xYourContractAddress'; // Replace with your contract's address

const YourContract = () => {
const contract = useContract({
address: contractAddress,
abi,
});

// Now you can call functions on the contract instance
};
```
</Tabs.Tab>
<Tabs.Tab>
```tsx
import { createContract } from 'viem';

const abi = './YourContract.json'; // Replace with your contract's ABI

const contractAddress = '0xYourContractAddress'; // Replace with your contract's address

const contract = createContract({
address: contractAddress,
abi,
});
```
</Tabs.Tab>
</Tabs>


## Reading Data from a Smart Contract

Reading data from a smart contract is similar to making a GET request in Web2. It does not require gas (unless you're interacting with a state-changing view function).


<Tabs items={['wagmi', 'viem']}>
<Tabs.Tab>
```tsx
import { useContractRead } from 'wagmi';

const YourContract = () => {
const { data, isError, isLoading } = useContractRead({
address: contractAddress,
abi,
functionName: 'yourReadFunction', // Replace with the function you want to call
});

if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error occurred</div>;

return <div>Data: {data?.toString()}</div>;
};
```
</Tabs.Tab>
<Tabs.Tab>
```tsx
import { readContract } from 'viem';

const YourContract = () => {
const fetchData = async () => {
const data = await readContract({
address: contractAddress,
abi,
functionName: 'yourReadFunction', // Replace with the function you want to call
});

return data;
};

React.useEffect(() => {
fetchData().then((data) => console.log(data));
}, []);

return <div>Check the console for contract data.</div>;
};
```
</Tabs.Tab>
</Tabs>

## Writing Data to a Smart Contract

<Tabs items={['wagmi', 'viem']}>
<Tabs.Tab>
```tsx
import { useContractWrite, useWaitForTransaction } from 'wagmi';

const YourContract = () => {
const { write, data, isError, isLoading } = useContractWrite({
address: contractAddress,
abi,
functionName: 'yourWriteFunction', // Replace with the function you want to call
});

const { isLoading: isTxLoading, isSuccess } = useWaitForTransaction({
hash: data?.hash,
});

if (isTxLoading) return <div>Transaction in progress...</div>;
if (isSuccess) return <div>Transaction successful!</div>;
if (isError) return <div>Error occurred during transaction</div>;

return <button onClick={() => write()}>Execute Transaction</button>;
};
```
</Tabs.Tab>
<Tabs.Tab>
```tsx
import { writeContract, waitForTransactionReceipt } from 'viem';

const YourContract = () => {
const handleWrite = async () => {
const transactionHash = await writeContract({
address: contractAddress,
abi,
functionName: 'yourWriteFunction', // Replace with the function you want to call
});

console.log('Transaction Hash:', transactionHash);
};

return <button onClick={handleWrite}>Execute Transaction</button>;
};
```
</Tabs.Tab>
</Tabs>

### Waiting for Transaction Receipt


Sometimes, you may want to wait for the transaction receipt instead of just monitoring the transaction status. A transaction receipt confirms that the transaction has been included in a block and is finalized. It provides detailed information about the transaction, such as the status, gas used, and any logs emitted during the execution.

<Tabs items={['wagmi', 'viem']}>
<Tabs.Tab>
```tsx
import { useContractWrite, useWaitForTransactionReceipt } from 'wagmi';

const YourContract = () => {
const { write, data, isError, isLoading } = useContractWrite({
address: contractAddress,
abi,
functionName: 'yourWriteFunction', // Replace with the function you want to call
});

const { isLoading: isReceiptLoading, isSuccess, data: receipt } = useWaitForTransactionReceipt({
hash: data?.hash,
});

if (isReceiptLoading) return <div>Waiting for receipt...</div>;
if (isSuccess) return <div>Transaction successful with receipt: {JSON.stringify(receipt)}</div>;
if (isError) return <div>Error occurred during transaction</div>;

return <button onClick={() => write()}>Execute Transaction</button>;
};
```
</Tabs.Tab>
<Tabs.Tab>
```tsx
import { waitForTransactionReceipt } from 'viem';

const YourContract = () => {
const handleWrite = async () => {
const transactionHash = await writeContract({
address: contractAddress,
abi,
functionName: 'yourWriteFunction', // Replace with the function you want to call
});

const receipt = await waitForTransactionReceipt({
hash: transactionHash,
});

console.log('Transaction Receipt:', receipt);
};

return <button onClick={handleWrite}>Execute Transaction</button>;
};
```
</Tabs.Tab>
</Tabs>

Empty file removed pages/build/ui/wagmi-hooks.mdx
Empty file.

0 comments on commit 56d1e7d

Please sign in to comment.