Skip to content

Commit

Permalink
Fixing transactioncontext
Browse files Browse the repository at this point in the history
  • Loading branch information
nadvolod committed Feb 20, 2022
1 parent 072b08b commit e904cb8
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 47 deletions.
10 changes: 10 additions & 0 deletions blockchain-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,13 @@ class ThemedButton extends React.Component {
}
}
```

# useEffect()

Accepts a function that contains imperative, possibly effectful code.

Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.

Instead, use useEffect. The function passed to useEffect will run after the render is committed to the screen. Think of effects as an escape hatch from React’s purely functional world into the imperative world.

By default, effects run after every completed render, but you can choose to fire them only when certain values have changed.
5 changes: 5 additions & 0 deletions blockchain-app/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"build": "vite build",
"preview": "vite preview",
"test:visual": "npx happo-e2e -- npx cypress run",
"test": "react-scripts test",
"happo": "happo run"
},
"dependencies": {
Expand All @@ -16,10 +17,14 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-scripts": "^5.0.0",
"vite": "^2.8.0"
},
"devDependencies": {
"@babel/core": "^7.17.2",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^13.5.0",
"@typescript-eslint/parser": "^5.12.0",
"autoprefixer": "^10.4.2",
"babel-loader": "^8.2.3",
Expand Down
30 changes: 15 additions & 15 deletions blockchain-app/client/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import './index.css';
import './index.css'
// imd
import { Navbar, Welcome, Footer, Services, Transactions } from './components';
import { Navbar, Welcome, Footer, Services, Transactions } from './components'

const App = () => {
return (
<div className='min-h-screen'>
<div className='gradient-bg-welcome'>
<Navbar />
<Welcome />
</div>
<Services />
<Transactions />
<Footer />
</div>
);
};
return (
<div className="min-h-screen">
<div className="gradient-bg-welcome">
<Navbar />
<Welcome />
</div>
<Services />
<Transactions />
<Footer />
</div>
)
}

export default App;
export default App
10 changes: 10 additions & 0 deletions blockchain-app/client/src/__tests__/Welcome.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import { render, fireEvent, waitFor, screen } from '@testing-library/react'
import Welcome from '../components/Welcome'

describe('Welcome', () => {
test('renders', () => {
render(<Welcome />)
screen.debug()
})
})
13 changes: 4 additions & 9 deletions blockchain-app/client/src/components/Welcome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import { BsInfoCircle } from 'react-icons/bs'
import Loader from './Loader'
import { TransactionContext } from '../context/TransactionContext'

const connectWallet = () => {
console.log('connectWallet')
}
const shortenAddress = () => {
console.log('shortenAddress')
}
Expand All @@ -16,7 +13,7 @@ const handleChange = () => {
}
const isLoading = () => false

function Input({ placeholder, name, type, value, handleChange }) {
const Input = ({ placeholder, name, type, value, handleChange }) => {
return (
<input
placeholder={placeholder}
Expand All @@ -35,11 +32,9 @@ const currentAccount = false
const companyCommonStyles =
'min-h-[70px] sm:px-0 px-2 sm:min-w-[120px] flex justify-center items-center border-[0.5px] border-gray-400 text-sm font-light text-white'

function Welcome() {
const Welcome = () => {
// consuming TransactionContext using useContext
const value = useContext(TransactionContext)

console.log(value)
const connectWallet = useContext(TransactionContext)

return (
<div className="flex w-full justify-center items-center">
Expand All @@ -55,7 +50,7 @@ function Welcome() {
{!currentAccount && (
<button
type="button"
onClick={connectWallet}
onClick={connectWallet.connectWallet}
className="flex flex-row justify-center items-center my-5 bg-[#2952e3] p-3 rounded-full cursor-pointer hover:bg-[#2546bd]"
>
<AiFillPlayCircle className="text-white mr-2" />
Expand Down
198 changes: 175 additions & 23 deletions blockchain-app/client/src/context/TransactionContext.jsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,183 @@
import React, { useEffect, useState } from 'react';
import { ethers } from 'ethers';
import { contractABI, contractAddress } from '../utils/constants';
/* eslint-disable no-undef */
import React, { useEffect, useState } from 'react'
import { ethers } from 'ethers'
import { contractABI, contractAddress } from '../utils/constants'

// create a context for transactions with no default value
export const TransactionContext = React.createContext();
export const TransactionContext = React.createContext()

// window.ethereum is enabled thanks to our Metamask extension
const { ethereum } = window;
const { ethereum } = window

const getEthereumContract = () => {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const transactionContract = new ethers.Contract(
contractAddress,
contractABI,
signer
);
const createEthereumContract = () => {
const provider = new ethers.providers.Web3Provider(ethereum)
const signer = provider.getSigner()
const transactionContract = new ethers.Contract(contractAddress, contractABI, signer)

console.log({ provider, signer, transactionContract });
};
return transactionContract
}

export const TransactionProvider = ({ children }) => {
return (
// using TransactionContext defined above, .Provider allows us to set
// a value to pass down to all of the children
<TransactionContext.Provider value='test'>
{children}
</TransactionContext.Provider>
);
};
const [formData, setFormData] = useState({
addressTo: '',
amount: '',
keyword: '',
message: '',
})
const [currentAccount, setCurrentAccount] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [transactionCount, setTransactionCount] = useState(
localStorage.getItem('transactionCount')
)
const [transactions, setTransactions] = useState([])

const handleChange = (e, name) => {
setformData((prevState) => ({ ...prevState, [name]: e.target.value }))
}

const getAllTransactions = async () => {
try {
if (ethereum) {
const transactionsContract = createEthereumContract()

const availableTransactions = await transactionsContract.getAllTransactions()

const structuredTransactions = availableTransactions.map((transaction) => ({
addressTo: transaction.receiver,
addressFrom: transaction.sender,
timestamp: new Date(transaction.timestamp.toNumber() * 1000).toLocaleString(),
message: transaction.message,
keyword: transaction.keyword,
amount: parseInt(transaction.amount._hex) / 10 ** 18,
}))

console.log(structuredTransactions)

setTransactions(structuredTransactions)
} else {
console.log('Ethereum is not present')
}
} catch (error) {
console.log(error)
}
}

const isWalletConnected = async () => {
try {
if (!ethereum) return alert('Please install MetaMask.')

const accounts = await ethereum.request({ method: 'eth_accounts' })

if (accounts.length) {
setCurrentAccount(accounts[0])

getAllTransactions()
} else {
console.log('No accounts found')
}
} catch (error) {
console.log(error)
}
}

const connectWallet = async () => {
try {
if (!ethereum) return alert('Please install MetaMask.')

const accounts = await ethereum.request({ method: 'eth_requestAccounts' })

setCurrentAccount(accounts[0])
window.location.reload()
} catch (error) {
console.log(error)

throw new Error('No ethereum object')
}
}

const doesTransactionExist = async () => {
try {
if (ethereum) {
const transactionsContract = createEthereumContract()
const currentTransactionCount = await transactionsContract.getTransactionCount()

window.localStorage.setItem('transactionCount', currentTransactionCount)
}
} catch (error) {
console.log(error)

throw new Error('No ethereum object')
}
}

const sendTransaction = async () => {
try {
if (ethereum) {
const { addressTo, amount, keyword, message } = formData
const transactionsContract = createEthereumContract()
const parsedAmount = ethers.utils.parseEther(amount)

await ethereum.request({
method: 'eth_sendTransaction',
params: [
{
from: currentAccount,
to: addressTo,
gas: '0x5208',
value: parsedAmount._hex,
},
],
})

const transactionHash = await transactionsContract.addToBlockchain(
addressTo,
parsedAmount,
message,
keyword
)

setIsLoading(true)
console.log(`Loading - ${transactionHash.hash}`)
await transactionHash.wait()
console.log(`Success - ${transactionHash.hash}`)
setIsLoading(false)

const transactionsCount = await transactionsContract.getTransactionCount()

setTransactionCount(transactionsCount.toNumber())
window.location.reload()
} else {
console.log('No ethereum object')
}
} catch (error) {
console.log(error)

throw new Error('No ethereum object')
}
}

// runs after the component is rendered
useEffect(() => {
isWalletConnected()
doesTransactionExist()
}, [transactionCount])

return (
// using TransactionContext defined above, .Provider allows us to set
// a value to pass down to all of the children
<TransactionContext.Provider
value={{
transactionCount,
connectWallet,
transactions,
currentAccount,
isLoading,
sendTransaction,
handleChange,
formData,
}}
>
{children}
</TransactionContext.Provider>
)
}

0 comments on commit e904cb8

Please sign in to comment.