Skip to content

Commit

Permalink
step 9b, 11a and 11b added
Browse files Browse the repository at this point in the history
  • Loading branch information
AliRa22aq committed Aug 5, 2022
1 parent 4a6424f commit 627068c
Show file tree
Hide file tree
Showing 51 changed files with 9,808 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
36 changes: 36 additions & 0 deletions step09b_read_smart_contracts_with_ethsdk_nextjs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
69 changes: 69 additions & 0 deletions step09b_read_smart_contracts_with_ethsdk_nextjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Read Smart Contracts using eth-sdk in Browser

[Mint Georli Ethers from this Faucet](https://goerlifaucet.com/)

[Mint Georli DAI from the contract mentioned in the post on Etherscan](https://ethereum.stackexchange.com/questions/72388/does-rinkeby-have-a-faucet-where-i-can-fill-a-wallet-with-dai)

[Georli DAI Contract](https://goerli.etherscan.io/address/0x97cb342Cf2F6EcF48c1285Fb8668f5a4237BF862)

npx create-next-app step09b_read_smart_contracts_with_ethsdk_nextjs --ts

We have two options to generate types:

1. [TypeChain](https://github.com/dethcrypto/TypeChain)
2. [eth-sdk](https://github.com/dethcrypto/eth-sdk)

TypeChain generates only TypeScript typings (d.ts) files, we will be using: eth-sdk. It generates typesafe, ready to use ethers.js wrappers and uses etherscan/sourcify to automatically get ABIs based only on smart contract addresses. Under the hood, eth-sdk relies on TypeChain.

npm install --save-dev @dethcrypto/eth-sdk @dethcrypto/eth-sdk-client ts-node ethers

Create a config file specifying contracts that we wish to interact with. Default path to this file is eth-sdk/eth-sdk.config.ts

yarn eth-sdk

When you run yarn eth-sdk. Few things will happen under the hood:

1. Etherscan API will be queried in search of ABIs corresponding to the addresses. ABIs will be downloaded into eth-sdk directory (you should commit them to git to speed up the process in the future).
2. Minimal SDK will be generated with functions like getMainnetSdk exposed. These functions wire addresses with ABIs and create ethers.js contract instances.
3. TypeScript types will be generated for SDK using TypeChain.
4. SDK is generated directly into node_modules, access it as @dethcrypto/eth-sdk-client.


Create index.ts file after reading the readme on github [eth-sdk](https://github.com/dethcrypto/eth-sdk)



This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { NextComponentType, NextPageContext } from "next";

interface Props {}

const Metamask: NextComponentType<NextPageContext, {}, Props> = (props: Props) => {
return (
<div
style={{
border: "0.5px solid #ccc",
display: "inline-block",
textAlign: "center",
margin: "10px",
padding: "20px",
fontSize: "20px",
}}
>
<p>
{" "}
It apprears that Metamask is not installed, <br />
Download <a href="https://metamask.io/">Metamask</a> to continue.
</p>
</div>
);
};

export default Metamask;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from '@dethcrypto/eth-sdk'

export default defineConfig({
contracts: {
goerli: {
dai: '0x97cb342Cf2F6EcF48c1285Fb8668f5a4237BF862',
},
},
})

// const address: string = '0x97cb342Cf2F6EcF48c1285Fb8668f5a4237BF862'; // DAI Contract https://goerli.etherscan.io/address/0x97cb342Cf2F6EcF48c1285Fb8668f5a4237BF862
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}

module.exports = nextConfig
28 changes: 28 additions & 0 deletions step09b_read_smart_contracts_with_ethsdk_nextjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "step09b_read_smart_contracts_with_ethsdk_nextjs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"ethers": "^5.6.9",
"next": "12.2.4",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@dethcrypto/eth-sdk": "^0.3.3",
"@dethcrypto/eth-sdk-client": "^0.1.6",
"@types/node": "18.6.4",
"@types/react": "18.0.15",
"@types/react-dom": "18.0.6",
"eslint": "8.21.0",
"eslint-config-next": "12.2.4",
"ts-node": "^10.9.1",
"typescript": "4.7.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}

export default MyApp
13 changes: 13 additions & 0 deletions step09b_read_smart_contracts_with_ethsdk_nextjs/pages/api/hello.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'

type Data = {
name: string
}

export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res.status(200).json({ name: 'John Doe' })
}
132 changes: 132 additions & 0 deletions step09b_read_smart_contracts_with_ethsdk_nextjs/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import type { NextPage } from 'next';
import { useState, useEffect } from "react";
import Metamask from "../component/Metamask";
import { ethers } from "ethers";
import { getGoerliSdk } from '@dethcrypto/eth-sdk-client' // yay, our SDK! It's tailored especially for our needs

interface ClientStatus{
isConnected: boolean;
address?: string;
balance?: string;
}


const Index: NextPage = () => {

const [haveMetamask, sethaveMetamask] = useState<boolean>(true);

const [clientStatus, setClientStatus] = useState<ClientStatus>({
isConnected: false,
});

let provider: ethers.providers.Web3Provider;

const checkConnection = async () => {
const { ethereum } = window as any;
if (ethereum) {
sethaveMetamask(true);

const accounts: string[] = await ethereum.request({ method: "eth_accounts" });
const {chainId} = await new ethers.providers.Web3Provider((window as any).ethereum).getNetwork();
console.log("chainId: ", chainId);

if(chainId !== 5){
alert("Please switch to Goerli testnet")
throw("NETWORK CHAIN ERROR")
}

if (accounts.length > 0) {
await updateBalance(accounts[0]);
} else {
setClientStatus({
isConnected: false,
});
}

} else {
sethaveMetamask(false);
}
};


const connectWeb3 = async () => {
//console.log("In ConnectWeb3: Start");
try {
const { ethereum } = window as any;

if (!ethereum) {
console.log("Metamask not detected");
return;
}

const accounts: string[] = await ethereum.request({method: "eth_requestAccounts"});


console.log("In ConnectWeb3: After")

await updateBalance(accounts[0]);

} catch (error) {
console.log("Error connecting to metamask", error);
}
};

const updateBalance = async(account: string) => {
// console.log("updateBalance: Begin");
provider = new ethers.providers.Web3Provider((window as any).ethereum);
const defaultSigner = ethers.Wallet.createRandom().connect(provider)
const sdk = getGoerliSdk(defaultSigner) // default signer will be wired with all contract instances
const balance: ethers.BigNumber = await sdk.dai.balanceOf(account);
const balanceFormated: string = ethers.utils.formatEther(balance);
console.log("updateBalance: Balance: " + balance);
setClientStatus({
isConnected: true,
address: account,
balance: balanceFormated
});

console.log("Balance" + clientStatus.balance);

};


useEffect(() => {
checkConnection();
}, []);


return (
<>
<section className="container d-flex">
<main>
<h1 className="main-title">Let's learn how to Read from a contract with eth-sdk</h1>

<div>
{!haveMetamask ? (
<Metamask />
) : clientStatus.isConnected ? (
<>
<br />
<h2>You're connected ✅</h2>
<div>My Metamask Account:</div>
<div>{clientStatus?.address}</div>
<div>My DAI Balance:</div>
<div>{clientStatus?.balance}</div>
</>
) : (
<>
<br />
<button className="btn connect-btn" onClick={connectWeb3}>
Connect Wallet
</button>
</>
)}
</div>
{/* ---- */}
</main>
</section>
</>
);
};

export default Index;
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 627068c

Please sign in to comment.