├── client ├── .gitignore ├── images │ ├── animated.svg │ ├── hello.svg │ └── logo.png ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── src │ ├── App.css │ ├── App.tsx │ ├── components │ │ ├── Footer │ │ │ └── Footer.tsx │ │ ├── Loader │ │ │ └── Loader.tsx │ │ ├── Navbar │ │ │ └── Navbar.tsx │ │ ├── Services │ │ │ └── Services.tsx │ │ ├── Transactions │ │ │ └── Transactions.tsx │ │ ├── Welcome │ │ │ └── Welcome.tsx │ │ └── index.tsx │ ├── context │ │ └── TransactionContext.tsx │ ├── favicon.svg │ ├── hooks │ │ └── useFetch.tsx │ ├── index.css │ ├── logo.svg │ ├── main.tsx │ ├── utils │ │ ├── Transactions.json │ │ ├── constants.ts │ │ ├── dummyData.ts │ │ └── shortenAddress.ts │ └── vite-env.d.ts ├── tailwind.config.js ├── tsconfig.json └── vite.config.ts └── smart_contract ├── .gitignore ├── README.md ├── contracts └── Transactions.sol ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts └── deploy.js └── test └── sample-test.js /client/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | .env 7 | .env.local 8 | 9 | .vercel 10 | -------------------------------------------------------------------------------- /client/images/animated.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/images/hello.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rman1223/web3_crypto/15c6140aa4d73c78511633a5f93e1a7d056ef53c/client/images/logo.png -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web3app", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "preview": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@tailwindcss/forms": "^0.4.0", 11 | "ethers": "^5.5.3", 12 | "react": "^17.0.2", 13 | "react-dom": "^17.0.2", 14 | "react-icons": "^4.3.1" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "^17.0.8", 18 | "@types/react": "^17.0.33", 19 | "@types/react-dom": "^17.0.10", 20 | "@vitejs/plugin-react": "^1.0.7", 21 | "autoprefixer": "^10.4.2", 22 | "postcss": "^8.4.5", 23 | "sass": "^1.48.0", 24 | "tailwindcss": "^3.0.13", 25 | "typescript": "^4.4.4", 26 | "vite": "^2.7.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /client/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /client/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | button { 41 | font-size: calc(10px + 2vmin); 42 | } 43 | -------------------------------------------------------------------------------- /client/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { Navbar, Footer, Loader, Transactions, Services, Welcome } from './components'; 3 | 4 | const App = () => { 5 | return ( 6 |
7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 |
16 | ); 17 | }; 18 | 19 | export default App; 20 | -------------------------------------------------------------------------------- /client/src/components/Footer/Footer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from '../../../images/logo.png'; 3 | 4 | const Footer = () => { 5 | return ( 6 |
7 |
8 |
9 | logo 10 |
11 |
12 |

Market

13 |

Exchange

14 |

Tutorials

15 |

Wallet

16 |
17 |
18 |
19 |

Come join us

20 |

info@crypto.com

21 |
22 | 23 |
24 | 25 |
26 |

@Cryptoapp 2022

27 |

All rights reserved

28 |
29 |
30 | ); 31 | }; 32 | 33 | export default Footer; 34 | -------------------------------------------------------------------------------- /client/src/components/Loader/Loader.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Loader = () => { 4 | return ( 5 |
6 |
7 |
8 | ); 9 | }; 10 | 11 | export default Loader; 12 | -------------------------------------------------------------------------------- /client/src/components/Navbar/Navbar.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from 'react'; 2 | import { HiMenuAlt4 } from 'react-icons/hi'; 3 | import { AiOutlineClose } from 'react-icons/ai'; 4 | import Logo from '../../../images/logo.png'; 5 | import { TransactionContext } from '../../context/TransactionContext'; 6 | 7 | const NavbarItem = ({ 8 | title, 9 | classProps = '', 10 | }: { 11 | title: string; 12 | classProps?: React.HTMLAttributes['className']; 13 | }) => { 14 | return
  • {title}
  • ; 15 | }; 16 | 17 | const Navbar = () => { 18 | const [toggleMenu, setToggleMenu] = useState(false); 19 | const { currentAccount, connectWallet } = useContext(TransactionContext); 20 | 21 | return ( 22 | 69 | ); 70 | }; 71 | 72 | export default Navbar; 73 | -------------------------------------------------------------------------------- /client/src/components/Services/Services.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BsShieldFillCheck } from 'react-icons/bs'; 3 | import { BiSearchAlt } from 'react-icons/bi'; 4 | import { RiHeart2Fill } from 'react-icons/ri'; 5 | 6 | interface ServiceCardProps { 7 | color: string; 8 | title: string; 9 | subtitle: string; 10 | icon: React.ReactNode; 11 | } 12 | 13 | const ServiceCard = ({ color, title, icon, subtitle }: ServiceCardProps) => { 14 | return ( 15 |
    16 |
    17 | {icon} 18 |
    19 |
    20 |

    {title}

    21 |

    {subtitle}

    22 |
    23 |
    24 | ); 25 | }; 26 | 27 | const Services = () => { 28 | return ( 29 |
    30 |
    31 |
    32 |

    33 | Services that we 34 |
    continue to improve 35 |

    36 |
    37 |
    38 | 39 |
    40 | } 44 | subtitle='Security is guranteed. We always maintain privacy and maintain the quality of our products' 45 | /> 46 | } 50 | subtitle='Security is guranteed. We always maintain privacy and maintain the quality of our products' 51 | /> 52 | } 56 | subtitle='Security is guranteed. We always maintain privacy and maintain the quality of our products' 57 | /> 58 |
    59 |
    60 | ); 61 | }; 62 | 63 | export default Services; 64 | -------------------------------------------------------------------------------- /client/src/components/Transactions/Transactions.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect } from 'react'; 2 | import { TransactionContext } from '../../context/TransactionContext'; 3 | import useFetch from '../../hooks/useFetch'; 4 | import dummyData from '../../utils/dummyData'; 5 | import { shortenAddress } from '../../utils/shortenAddress'; 6 | 7 | interface TransactionCardProps { 8 | addressTo: string; 9 | addressFrom: string; 10 | amount: string; 11 | message: string; 12 | url: React.ImgHTMLAttributes['src']; 13 | timestamp: string; 14 | keyword?: string; 15 | } 16 | 17 | const TransactionCard = ({ 18 | addressTo, 19 | addressFrom, 20 | timestamp, 21 | message, 22 | amount, 23 | url, 24 | keyword, 25 | }: TransactionCardProps) => { 26 | const gifUrl = useFetch({ keyword } as any); 27 | console.log('keyword: ', keyword); 28 | return ( 29 |
    37 |
    38 |
    39 | 43 |

    From: {shortenAddress(addressFrom)}

    44 |
    45 | 46 | 50 |

    To: {shortenAddress(addressTo)}

    51 |
    52 | 53 |

    Amount: {amount} ETH

    54 | 55 | {message && ( 56 | <> 57 |
    58 |

    Message: {message}

    59 | 60 | )} 61 |
    62 | {gifUrl && ( 63 | {keyword} 68 | )} 69 | 70 |
    71 |

    {timestamp}

    72 |
    73 |
    74 |
    75 | ); 76 | }; 77 | 78 | const Transactions = () => { 79 | const { currentAccount, transactions, transactionCount } = useContext(TransactionContext); 80 | 81 | return ( 82 |
    83 |
    84 | {currentAccount ? ( 85 |

    Latest Transactions

    86 | ) : ( 87 |

    88 | Connect your account to see the last changes 89 |

    90 | )} 91 | 92 | {/* Connect your account to see last transactions */} 93 |
    94 | {transactions.reverse().map((transaction, index) => { 95 | return ; 96 | })} 97 |
    98 |
    99 |
    100 | ); 101 | }; 102 | 103 | export default Transactions; 104 | -------------------------------------------------------------------------------- /client/src/components/Welcome/Welcome.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect } from 'react'; 2 | import { AiFillPlayCircle } from 'react-icons/ai'; 3 | import { SiEthereum } from 'react-icons/si'; 4 | import { BsInfoCircle } from 'react-icons/bs'; 5 | import { Loader } from '..'; 6 | import { TransactionContext } from '../../context/TransactionContext'; 7 | import { shortenAddress } from '../../utils/shortenAddress'; 8 | 9 | const commonStyles = 10 | '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'; 11 | 12 | interface InputProps { 13 | placeholder: string; 14 | name: string; 15 | type: React.HTMLInputTypeAttribute; 16 | handleChange: (e: React.ChangeEvent, name: string) => void; 17 | value?: string; 18 | } 19 | 20 | const Input: React.FC = ({ placeholder, name, type, handleChange, value }) => ( 21 | handleChange(e, name)} 26 | step='0.0001' 27 | value={value} 28 | className='w-full p-2 my-2 text-sm text-white bg-transparent border-none rounded-sm outline-none white-glassmorphism' 29 | /> 30 | ); 31 | 32 | const Welcome = () => { 33 | const { connectWallet, currentAccount, formData, isLoading, handleChange, sendTransactions } = 34 | useContext(TransactionContext); 35 | 36 | const handleSubmit = (e: React.MouseEvent) => { 37 | const { addressTo, amount, message, keyword } = formData; 38 | 39 | e.preventDefault(); 40 | 41 | if (addressTo === '' || amount === '' || keyword === '' || message === '') { 42 | return alert('Please fill all fields'); 43 | } 44 | 45 | sendTransactions(); 46 | }; 47 | 48 | const { addressTo, amount, message, keyword } = formData; 49 | 50 | useEffect(() => { 51 | console.log('data form: ', { addressTo, amount, message, keyword }); 52 | }, [formData]); 53 | 54 | return ( 55 |
    56 |
    57 |
    58 |

    59 | Send Crypto
    across world 60 |

    61 |

    62 | Explore the crypto world. Buy and sell cryptocurrencies easily on Krypto. 63 |

    64 | {!currentAccount && ( 65 | 71 | )} 72 | 73 |
    74 |
    Reliability
    75 |
    Security
    76 |
    Ethereum
    77 |
    Web 3.0
    78 |
    Low fees
    79 |
    Blockchain
    80 |
    81 |
    82 |
    83 |
    84 |
    85 |
    86 |
    87 | 88 |
    89 | 90 |
    91 |
    92 |

    {shortenAddress(currentAccount)}

    93 |

    Ethereum

    94 |
    95 |
    96 |
    97 | 98 |
    99 | 105 | 111 | 117 | 123 |
    124 | {isLoading ? ( 125 | 126 | ) : ( 127 | 133 | )} 134 |
    135 |
    136 |
    137 |
    138 | ); 139 | }; 140 | 141 | export default Welcome; 142 | -------------------------------------------------------------------------------- /client/src/components/index.tsx: -------------------------------------------------------------------------------- 1 | import Footer from './Footer/Footer'; 2 | import Navbar from './Navbar/Navbar'; 3 | import Loader from './Loader/Loader'; 4 | import Services from './Services/Services'; 5 | import Transactions from './Transactions/Transactions'; 6 | import Welcome from './Welcome/Welcome'; 7 | 8 | export { Footer, Navbar, Loader, Services, Transactions, Welcome }; 9 | -------------------------------------------------------------------------------- /client/src/context/TransactionContext.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, createContext } from 'react'; 2 | import { ethers } from 'ethers'; 3 | import { contractABI, contractAddress } from '../utils/constants'; 4 | 5 | interface TransactionContextProps { 6 | children: React.ReactNode; 7 | } 8 | 9 | type AppContextState = { addressTo: string; amount: string; keyword: string; message: string }; 10 | 11 | const initialState = { 12 | connectWallet: () => {}, 13 | currentAccount: '', 14 | handleChange: (e: React.ChangeEvent, name: string) => {}, 15 | formData: { addressTo: '', amount: '', keyword: '', message: '' }, 16 | setFormData: (state: AppContextState) => {}, 17 | sendTransactions: () => {}, 18 | transactions: [], 19 | isLoading: false, 20 | transactionCount: 0, 21 | }; 22 | 23 | export const TransactionContext = createContext(initialState); 24 | 25 | const { ethereum }: any = window; 26 | 27 | const getEthereumContract = () => { 28 | const provider = new ethers.providers.Web3Provider(ethereum); 29 | const signer = provider.getSigner(); 30 | const transactionsContract = new ethers.Contract(contractAddress, contractABI, signer); 31 | 32 | console.log('web3 ', { 33 | provider, 34 | signer, 35 | transactionsContract, 36 | }); 37 | 38 | return transactionsContract; 39 | }; 40 | 41 | const createEthereumContract = () => { 42 | const provider = new ethers.providers.Web3Provider(ethereum); 43 | const signer = provider.getSigner(); 44 | const transactionsContract = new ethers.Contract(contractAddress, contractABI, signer); 45 | 46 | return transactionsContract; 47 | }; 48 | 49 | export const TransactionsProvider = ({ children }: TransactionContextProps) => { 50 | const [currentAccount, setCurrentAccount] = useState(''); 51 | const [formData, setFormData] = useState({ addressTo: '', amount: '', keyword: '', message: '' }); 52 | const [isLoading, setIsLoading] = useState(false); 53 | const [transactionCount, setTransactionCount] = useState( 54 | Number(localStorage.getItem('transactionCount')) || 0 55 | ); 56 | const [transactions, setTransactions] = useState([]); 57 | 58 | const handleChange = (e: React.ChangeEvent, name: string) => { 59 | setFormData((prev) => ({ 60 | ...prev, 61 | [name]: e.target.value, 62 | })); 63 | }; 64 | 65 | const getAllTransactions = async () => { 66 | try { 67 | if (ethereum) { 68 | const transactionsContract = createEthereumContract(); 69 | 70 | const availableTransactions = await transactionsContract.getAllTransactions(); 71 | 72 | const structuredTransactions = availableTransactions.map((transaction: any) => ({ 73 | addressTo: transaction.receiver, 74 | addressFrom: transaction.from, 75 | timestamp: new Date(transaction.timestamp.toNumber() * 1000).toLocaleString(), 76 | message: transaction.message, 77 | keyword: transaction.keyword, 78 | amount: parseInt(transaction.amount._hex) / 10 ** 18, 79 | })); 80 | 81 | console.log('structuredTransactions: ', structuredTransactions); 82 | 83 | setTransactions(structuredTransactions); 84 | } else { 85 | console.log('Ethereum is not present'); 86 | } 87 | } catch (error) { 88 | console.log(error); 89 | } 90 | }; 91 | 92 | const checkIfTransactionExist = async () => { 93 | try { 94 | const transactionContract = getEthereumContract(); 95 | const transactionCount = await transactionContract.getTransactionCount(); 96 | 97 | window.localStorage.setItem('transactionCount', transactionCount); 98 | } catch (error) { 99 | console.log(error); 100 | throw new Error('No eth object!'); 101 | } 102 | }; 103 | 104 | const checkIfWalletConnected = async () => { 105 | try { 106 | if (!ethereum) { 107 | return alert('Please install metamask!'); 108 | } 109 | 110 | const accounts: any[] = await ethereum.request({ method: 'eth_accounts' }); 111 | 112 | if (accounts.length) { 113 | setCurrentAccount(accounts[0]); 114 | 115 | // get all transactions 116 | getAllTransactions(); 117 | } else { 118 | console.log('No accounts found!'); 119 | } 120 | } catch (error) { 121 | console.log('error ', error); 122 | } 123 | }; 124 | 125 | const connectWallet = async () => { 126 | try { 127 | if (!ethereum) { 128 | return alert('Please install metamask!'); 129 | } 130 | const accounts = await ethereum.request({ method: 'eth_requestAccounts' }); 131 | 132 | setCurrentAccount(accounts[0]); 133 | } catch (e) { 134 | console.log('error: ', e); 135 | throw new Error('No eth object!'); 136 | } 137 | }; 138 | 139 | const sendTransactions = async () => { 140 | try { 141 | if (!ethereum) { 142 | return alert('Please install metamask!'); 143 | } 144 | const { addressTo, amount, message, keyword } = formData; 145 | const transactionContract = getEthereumContract(); 146 | const parsedAmount = ethers.utils.parseEther(amount); 147 | await ethereum.request({ 148 | method: 'eth_sendTransaction', 149 | params: [ 150 | { 151 | from: currentAccount, 152 | to: addressTo, 153 | gas: '0x5208', // 21000 154 | value: parsedAmount._hex, 155 | }, 156 | ], 157 | }); 158 | 159 | const transactionHash = await transactionContract.addToBlockChain( 160 | addressTo, 161 | parsedAmount, 162 | message, 163 | keyword 164 | ); 165 | 166 | setIsLoading(true); 167 | 168 | console.log(`Loading - ${transactionHash.hash}`); 169 | 170 | await transactionHash.wait(); 171 | 172 | setIsLoading(false); 173 | 174 | console.log(`Success - ${transactionHash.hash}`); 175 | 176 | const transactionCount = await transactionContract.getTransactionCount(); 177 | 178 | setTransactionCount(transactionCount.toNumber()); 179 | 180 | window.location.reload(); 181 | } catch (error) { 182 | console.log('error:', error); 183 | } 184 | }; 185 | 186 | useEffect(() => { 187 | checkIfWalletConnected(); 188 | checkIfTransactionExist(); 189 | }, [transactionCount]); 190 | 191 | return ( 192 | 204 | {children} 205 | 206 | ); 207 | }; 208 | -------------------------------------------------------------------------------- /client/src/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /client/src/hooks/useFetch.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | 3 | const APIKEY = import.meta.env.VITE_GIPHY_API; 4 | 5 | interface useFetchProps { 6 | keyword: string; 7 | } 8 | 9 | const useFetch = ({ keyword }: useFetchProps) => { 10 | const [gifUrl, setGifUrl] = useState(''); 11 | 12 | const fetchGifs = async () => { 13 | await fetch( 14 | `https://api.giphy.com/v1/gifs/search?api_key=${APIKEY}&q=${keyword 15 | .split(' ') 16 | .join('')}&limit=1` 17 | ) 18 | .then((res) => res.json()) 19 | .then(({ data }) => { 20 | setGifUrl(data?.[0]?.images?.downsized_medium?.url); 21 | if (!data.length) { 22 | setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif'); 23 | } 24 | }) 25 | .catch((err) => { 26 | console.log(err); 27 | setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif'); 28 | }); 29 | }; 30 | 31 | useEffect(() => { 32 | if (keyword) { 33 | console.log('keyword: ', keyword.split(' ').join('')); 34 | fetchGifs(); 35 | } 36 | }, [keyword]); 37 | 38 | return gifUrl; 39 | }; 40 | 41 | export default useFetch; 42 | -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap'); 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | * html { 8 | padding: 0; 9 | margin: 0; 10 | box-sizing: border-box; 11 | } 12 | 13 | body { 14 | margin: 0; 15 | font-family: 'Open Sans', sans-serif; 16 | -webkit-font-smoothing: antialiased; 17 | -moz-osx-font-smoothing: grayscale; 18 | } 19 | 20 | .gradient-bg-welcome { 21 | background-color: #0f0e13; 22 | background-image: radial-gradient(at 0% 0%, hsla(253, 16%, 7%, 1) 0, transparent 50%), 23 | radial-gradient(at 50% 0%, hsla(225, 39%, 30%, 1) 0, transparent 50%), 24 | radial-gradient(at 100% 0%, hsla(339, 49%, 30%, 1) 0, transparent 50%); 25 | } 26 | 27 | .gradient-bg-services { 28 | background-color: #0f0e13; 29 | background-image: radial-gradient(at 0% 0%, hsla(253, 16%, 7%, 1) 0, transparent 50%), 30 | radial-gradient(at 50% 100%, hsla(225, 39%, 25%, 1) 0, transparent 50%); 31 | } 32 | 33 | .gradient-bg-transactions { 34 | background-color: #0f0e13; 35 | background-image: radial-gradient(at 0% 100%, hsla(253, 16%, 7%, 1) 0, transparent 50%), 36 | radial-gradient(at 50% 0%, hsla(225, 39%, 25%, 1) 0, transparent 50%); 37 | } 38 | 39 | .gradient-bg-footer { 40 | background-color: #0f0e13; 41 | background-image: radial-gradient(at 0% 100%, hsla(253, 16%, 7%, 1) 0, transparent 53%), 42 | radial-gradient(at 50% 150%, hsla(339, 49%, 30%, 1) 0, transparent 50%); 43 | } 44 | 45 | .blue-glassmorphism { 46 | background: rgb(39, 51, 89, 0.4); 47 | border-radius: 16px; 48 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2); 49 | backdrop-filter: blur(5px); 50 | -webkit-backdrop-filter: blur(5px); 51 | border: 1px solid rgba(0, 0, 0, 0.3); 52 | } 53 | 54 | /* white glassmorphism */ 55 | .white-glassmorphism { 56 | background: rgba(255, 255, 255, 0.05); 57 | border-radius: 16px; 58 | backdrop-filter: blur(5px); 59 | -webkit-backdrop-filter: blur(5px); 60 | border: 1px solid rgba(255, 255, 255, 0.3); 61 | } 62 | 63 | .eth-card { 64 | background-color: #a099ff; 65 | background-image: radial-gradient(at 83% 67%, rgb(152, 231, 156) 0, transparent 58%), 66 | radial-gradient(at 67% 20%, hsla(357, 94%, 71%, 1) 0, transparent 59%), 67 | radial-gradient(at 88% 35%, hsla(222, 81%, 65%, 1) 0, transparent 50%), 68 | radial-gradient(at 31% 91%, hsla(9, 61%, 61%, 1) 0, transparent 52%), 69 | radial-gradient(at 27% 71%, hsla(336, 91%, 65%, 1) 0, transparent 49%), 70 | radial-gradient(at 74% 89%, hsla(30, 98%, 65%, 1) 0, transparent 51%), 71 | radial-gradient(at 53% 75%, hsla(174, 94%, 68%, 1) 0, transparent 45%); 72 | } 73 | 74 | .text-gradient { 75 | background-color: #fff; 76 | background-image: radial-gradient(at 4% 36%, hsla(0, 0%, 100%, 1) 0, transparent 53%), 77 | radial-gradient(at 100% 60%, rgb(0, 0, 0) 0, transparent 50%); 78 | -webkit-background-clip: text; 79 | -webkit-text-fill-color: transparent; 80 | } 81 | -------------------------------------------------------------------------------- /client/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import { TransactionsProvider } from './context/TransactionContext'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ); 15 | -------------------------------------------------------------------------------- /client/src/utils/Transactions.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Transactions", 4 | "sourceName": "contracts/Transactions.sol", 5 | "abi": [ 6 | { 7 | "anonymous": false, 8 | "inputs": [ 9 | { 10 | "indexed": false, 11 | "internalType": "address", 12 | "name": "from", 13 | "type": "address" 14 | }, 15 | { 16 | "indexed": false, 17 | "internalType": "address", 18 | "name": "receiver", 19 | "type": "address" 20 | }, 21 | { 22 | "indexed": false, 23 | "internalType": "uint256", 24 | "name": "amount", 25 | "type": "uint256" 26 | }, 27 | { 28 | "indexed": false, 29 | "internalType": "string", 30 | "name": "message", 31 | "type": "string" 32 | }, 33 | { 34 | "indexed": false, 35 | "internalType": "uint256", 36 | "name": "timestamp", 37 | "type": "uint256" 38 | }, 39 | { 40 | "indexed": false, 41 | "internalType": "string", 42 | "name": "keyword", 43 | "type": "string" 44 | } 45 | ], 46 | "name": "Transfer", 47 | "type": "event" 48 | }, 49 | { 50 | "inputs": [ 51 | { 52 | "internalType": "address payable", 53 | "name": "receiver", 54 | "type": "address" 55 | }, 56 | { 57 | "internalType": "uint256", 58 | "name": "amount", 59 | "type": "uint256" 60 | }, 61 | { 62 | "internalType": "string", 63 | "name": "message", 64 | "type": "string" 65 | }, 66 | { 67 | "internalType": "string", 68 | "name": "keyword", 69 | "type": "string" 70 | } 71 | ], 72 | "name": "addToBlockChain", 73 | "outputs": [], 74 | "stateMutability": "nonpayable", 75 | "type": "function" 76 | }, 77 | { 78 | "inputs": [], 79 | "name": "getAllTransactions", 80 | "outputs": [ 81 | { 82 | "components": [ 83 | { 84 | "internalType": "address", 85 | "name": "from", 86 | "type": "address" 87 | }, 88 | { 89 | "internalType": "address", 90 | "name": "receiver", 91 | "type": "address" 92 | }, 93 | { 94 | "internalType": "uint256", 95 | "name": "amount", 96 | "type": "uint256" 97 | }, 98 | { 99 | "internalType": "string", 100 | "name": "message", 101 | "type": "string" 102 | }, 103 | { 104 | "internalType": "uint256", 105 | "name": "timestamp", 106 | "type": "uint256" 107 | }, 108 | { 109 | "internalType": "string", 110 | "name": "keyword", 111 | "type": "string" 112 | } 113 | ], 114 | "internalType": "struct Transactions.TransferStruct[]", 115 | "name": "", 116 | "type": "tuple[]" 117 | } 118 | ], 119 | "stateMutability": "view", 120 | "type": "function" 121 | }, 122 | { 123 | "inputs": [], 124 | "name": "getTransactionCount", 125 | "outputs": [ 126 | { 127 | "internalType": "uint256", 128 | "name": "", 129 | "type": "uint256" 130 | } 131 | ], 132 | "stateMutability": "view", 133 | "type": "function" 134 | } 135 | ], 136 | "bytecode": "0x608060405234801561001057600080fd5b50610c0d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806327506f53146100465780632e7700f014610064578063b2da096014610082575b600080fd5b61004e61009e565b60405161005b91906108b9565b60405180910390f35b61006c6102e1565b60405161007991906108db565b60405180910390f35b61009c600480360381019061009791906105e1565b6102ea565b005b60606001805480602002602001604051908101604052809291908181526020016000905b828210156102d857838290600052602060002090600602016040518060c00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820180546101ab90610ad9565b80601f01602080910402602001604051908101604052809291908181526020018280546101d790610ad9565b80156102245780601f106101f957610100808354040283529160200191610224565b820191906000526020600020905b81548152906001019060200180831161020757829003601f168201915b505050505081526020016004820154815260200160058201805461024790610ad9565b80601f016020809104026020016040519081016040528092919081815260200182805461027390610ad9565b80156102c05780601f10610295576101008083540402835291602001916102c0565b820191906000526020600020905b8154815290600101906020018083116102a357829003601f168201915b505050505081525050815260200190600101906100c2565b50505050905090565b60008054905090565b60016000808282546102fc91906109bd565b9250508190555060016040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184815260200142815260200183815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301908051906020019061043b9291906104ac565b506080820151816004015560a08201518160050190805190602001906104629291906104ac565b5050507f416cfa4330a4565f45c2fd2dd4826a83a37443aba2ce6f79477c7355afac35fa33858585428660405161049e9695949392919061084a565b60405180910390a150505050565b8280546104b890610ad9565b90600052602060002090601f0160209004810192826104da5760008555610521565b82601f106104f357805160ff1916838001178555610521565b82800160010185558215610521579182015b82811115610520578251825591602001919060010190610505565b5b50905061052e9190610532565b5090565b5b8082111561054b576000816000905550600101610533565b5090565b600061056261055d84610927565b6108f6565b90508281526020810184848401111561057a57600080fd5b610585848285610a97565b509392505050565b60008135905061059c81610ba9565b92915050565b600082601f8301126105b357600080fd5b81356105c384826020860161054f565b91505092915050565b6000813590506105db81610bc0565b92915050565b600080600080608085870312156105f757600080fd5b60006106058782880161058d565b9450506020610616878288016105cc565b935050604085013567ffffffffffffffff81111561063357600080fd5b61063f878288016105a2565b925050606085013567ffffffffffffffff81111561065c57600080fd5b610668878288016105a2565b91505092959194509250565b6000610680838361079c565b905092915050565b61069181610a61565b82525050565b6106a081610a13565b82525050565b6106af81610a13565b82525050565b60006106c082610967565b6106ca818561098a565b9350836020820285016106dc85610957565b8060005b8581101561071857848403895281516106f98582610674565b94506107048361097d565b925060208a019950506001810190506106e0565b50829750879550505050505092915050565b600061073582610972565b61073f818561099b565b935061074f818560208601610aa6565b61075881610b98565b840191505092915050565b600061076e82610972565b61077881856109ac565b9350610788818560208601610aa6565b61079181610b98565b840191505092915050565b600060c0830160008301516107b46000860182610697565b5060208301516107c76020860182610697565b5060408301516107da604086018261082c565b50606083015184820360608601526107f2828261072a565b9150506080830151610807608086018261082c565b5060a083015184820360a086015261081f828261072a565b9150508091505092915050565b61083581610a57565b82525050565b61084481610a57565b82525050565b600060c08201905061085f60008301896106a6565b61086c6020830188610688565b610879604083018761083b565b818103606083015261088b8186610763565b905061089a608083018561083b565b81810360a08301526108ac8184610763565b9050979650505050505050565b600060208201905081810360008301526108d381846106b5565b905092915050565b60006020820190506108f0600083018461083b565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561091d5761091c610b69565b5b8060405250919050565b600067ffffffffffffffff82111561094257610941610b69565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006109c882610a57565b91506109d383610a57565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610a0857610a07610b0b565b5b828201905092915050565b6000610a1e82610a37565b9050919050565b6000610a3082610a37565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610a6c82610a73565b9050919050565b6000610a7e82610a85565b9050919050565b6000610a9082610a37565b9050919050565b82818337600083830152505050565b60005b83811015610ac4578082015181840152602081019050610aa9565b83811115610ad3576000848401525b50505050565b60006002820490506001821680610af157607f821691505b60208210811415610b0557610b04610b3a565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b610bb281610a25565b8114610bbd57600080fd5b50565b610bc981610a57565b8114610bd457600080fd5b5056fea26469706673582212205396c81e995d22bbc2272c12cc4998aa414c5cabf2cd94f932fbd4596978663464736f6c63430008000033", 137 | "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806327506f53146100465780632e7700f014610064578063b2da096014610082575b600080fd5b61004e61009e565b60405161005b91906108b9565b60405180910390f35b61006c6102e1565b60405161007991906108db565b60405180910390f35b61009c600480360381019061009791906105e1565b6102ea565b005b60606001805480602002602001604051908101604052809291908181526020016000905b828210156102d857838290600052602060002090600602016040518060c00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820180546101ab90610ad9565b80601f01602080910402602001604051908101604052809291908181526020018280546101d790610ad9565b80156102245780601f106101f957610100808354040283529160200191610224565b820191906000526020600020905b81548152906001019060200180831161020757829003601f168201915b505050505081526020016004820154815260200160058201805461024790610ad9565b80601f016020809104026020016040519081016040528092919081815260200182805461027390610ad9565b80156102c05780601f10610295576101008083540402835291602001916102c0565b820191906000526020600020905b8154815290600101906020018083116102a357829003601f168201915b505050505081525050815260200190600101906100c2565b50505050905090565b60008054905090565b60016000808282546102fc91906109bd565b9250508190555060016040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184815260200142815260200183815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301908051906020019061043b9291906104ac565b506080820151816004015560a08201518160050190805190602001906104629291906104ac565b5050507f416cfa4330a4565f45c2fd2dd4826a83a37443aba2ce6f79477c7355afac35fa33858585428660405161049e9695949392919061084a565b60405180910390a150505050565b8280546104b890610ad9565b90600052602060002090601f0160209004810192826104da5760008555610521565b82601f106104f357805160ff1916838001178555610521565b82800160010185558215610521579182015b82811115610520578251825591602001919060010190610505565b5b50905061052e9190610532565b5090565b5b8082111561054b576000816000905550600101610533565b5090565b600061056261055d84610927565b6108f6565b90508281526020810184848401111561057a57600080fd5b610585848285610a97565b509392505050565b60008135905061059c81610ba9565b92915050565b600082601f8301126105b357600080fd5b81356105c384826020860161054f565b91505092915050565b6000813590506105db81610bc0565b92915050565b600080600080608085870312156105f757600080fd5b60006106058782880161058d565b9450506020610616878288016105cc565b935050604085013567ffffffffffffffff81111561063357600080fd5b61063f878288016105a2565b925050606085013567ffffffffffffffff81111561065c57600080fd5b610668878288016105a2565b91505092959194509250565b6000610680838361079c565b905092915050565b61069181610a61565b82525050565b6106a081610a13565b82525050565b6106af81610a13565b82525050565b60006106c082610967565b6106ca818561098a565b9350836020820285016106dc85610957565b8060005b8581101561071857848403895281516106f98582610674565b94506107048361097d565b925060208a019950506001810190506106e0565b50829750879550505050505092915050565b600061073582610972565b61073f818561099b565b935061074f818560208601610aa6565b61075881610b98565b840191505092915050565b600061076e82610972565b61077881856109ac565b9350610788818560208601610aa6565b61079181610b98565b840191505092915050565b600060c0830160008301516107b46000860182610697565b5060208301516107c76020860182610697565b5060408301516107da604086018261082c565b50606083015184820360608601526107f2828261072a565b9150506080830151610807608086018261082c565b5060a083015184820360a086015261081f828261072a565b9150508091505092915050565b61083581610a57565b82525050565b61084481610a57565b82525050565b600060c08201905061085f60008301896106a6565b61086c6020830188610688565b610879604083018761083b565b818103606083015261088b8186610763565b905061089a608083018561083b565b81810360a08301526108ac8184610763565b9050979650505050505050565b600060208201905081810360008301526108d381846106b5565b905092915050565b60006020820190506108f0600083018461083b565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561091d5761091c610b69565b5b8060405250919050565b600067ffffffffffffffff82111561094257610941610b69565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006109c882610a57565b91506109d383610a57565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610a0857610a07610b0b565b5b828201905092915050565b6000610a1e82610a37565b9050919050565b6000610a3082610a37565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610a6c82610a73565b9050919050565b6000610a7e82610a85565b9050919050565b6000610a9082610a37565b9050919050565b82818337600083830152505050565b60005b83811015610ac4578082015181840152602081019050610aa9565b83811115610ad3576000848401525b50505050565b60006002820490506001821680610af157607f821691505b60208210811415610b0557610b04610b3a565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b610bb281610a25565b8114610bbd57600080fd5b50565b610bc981610a57565b8114610bd457600080fd5b5056fea26469706673582212205396c81e995d22bbc2272c12cc4998aa414c5cabf2cd94f932fbd4596978663464736f6c63430008000033", 138 | "linkReferences": {}, 139 | "deployedLinkReferences": {} 140 | } 141 | -------------------------------------------------------------------------------- /client/src/utils/constants.ts: -------------------------------------------------------------------------------- 1 | import abi from './Transactions.json'; 2 | 3 | export const contractAddress = '0xbA1252D38fAC5AFa1fe74b7661c1a062C4D1a0D3'; 4 | 5 | export const contractABI = abi.abi; 6 | -------------------------------------------------------------------------------- /client/src/utils/dummyData.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | id: 1, 4 | url: 'https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif?quality=90&strip=all&zoom=1&resize=500%2C284', 5 | message: '', 6 | timestamp: '12/21/2021, 4:33:21 PM', 7 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90', 8 | amount: '0.01', 9 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE', 10 | }, 11 | { 12 | id: 2, 13 | url: 'https://media4.popsugar-assets.com/files/2013/11/07/832/n/1922398/eb7a69a76543358d_28.gif', 14 | message: '', 15 | timestamp: '12/21/2021, 4:33:21 PM', 16 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90', 17 | amount: '0.01', 18 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE', 19 | }, 20 | { 21 | id: 3, 22 | url: 'https://acegif.com/wp-content/uploads/gif-shaking-head-38.gif', 23 | message: '', 24 | timestamp: '12/21/2021, 4:33:21 PM', 25 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90', 26 | amount: '0.01', 27 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE', 28 | }, 29 | { 30 | id: 4, 31 | url: 'https://i.pinimg.com/originals/68/a0/9e/68a09e774e98242871c2db0f99307420.gif', 32 | message: '', 33 | timestamp: '12/21/2021, 4:33:21 PM', 34 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90', 35 | amount: '0.01', 36 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE', 37 | }, 38 | { 39 | id: 5, 40 | url: 'https://i.pinimg.com/originals/73/d3/a1/73d3a14d212314ab1f7268b71d639c15.gif', 41 | message: '', 42 | timestamp: '12/21/2021, 4:33:21 PM', 43 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90', 44 | amount: '0.01', 45 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE', 46 | }, 47 | { 48 | id: 6, 49 | url: 'https://www.omnisend.com/blog/wp-content/uploads/2016/09/funny-gifs-9.gif', 50 | message: '', 51 | timestamp: '12/21/2021, 4:33:21 PM', 52 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90', 53 | amount: '0.01', 54 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE', 55 | }, 56 | ]; 57 | -------------------------------------------------------------------------------- /client/src/utils/shortenAddress.ts: -------------------------------------------------------------------------------- 1 | export const shortenAddress = (address: string) => { 2 | return `${address.slice(0, 6)}...${address.slice(address.length - 4)}`; 3 | }; 4 | -------------------------------------------------------------------------------- /client/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /client/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'], 3 | mode: 'jit', 4 | darkMode: false, // or 'media' or 'class' 5 | theme: { 6 | fontFamily: { 7 | display: ['Open Sans', 'sans-serif'], 8 | body: ['Open Sans', 'sans-serif'], 9 | }, 10 | extend: { 11 | screens: { 12 | mf: '990px', 13 | }, 14 | keyframes: { 15 | 'slide-in': { 16 | '0%': { 17 | '-webkit-transform': 'translateX(120%)', 18 | transform: 'translateX(120%)', 19 | }, 20 | '100%': { 21 | '-webkit-transform': 'translateX(0%)', 22 | transform: 'translateX(0%)', 23 | }, 24 | }, 25 | }, 26 | animation: { 27 | 'slide-in': 'slide-in 0.5s ease-out', 28 | }, 29 | }, 30 | }, 31 | variants: { 32 | extend: {}, 33 | }, 34 | plugins: [require('@tailwindcss/forms')], 35 | }; 36 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": false, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "types": ["vite/client"] 19 | }, 20 | "include": ["./src"] 21 | } 22 | -------------------------------------------------------------------------------- /client/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()] 7 | }) 8 | -------------------------------------------------------------------------------- /smart_contract/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | 7 | #Hardhat files 8 | cache 9 | artifacts 10 | -------------------------------------------------------------------------------- /smart_contract/README.md: -------------------------------------------------------------------------------- 1 | # Basic Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat accounts 9 | npx hardhat compile 10 | npx hardhat clean 11 | npx hardhat test 12 | npx hardhat node 13 | node scripts/sample-script.js 14 | npx hardhat help 15 | ``` 16 | -------------------------------------------------------------------------------- /smart_contract/contracts/Transactions.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicensed 2 | pragma solidity ^0.8.0; 3 | 4 | contract Transactions { 5 | uint256 transactionsCount; 6 | 7 | event Transfer( 8 | address from, 9 | address receiver, 10 | uint256 amount, 11 | string message, 12 | uint256 timestamp, 13 | string keyword 14 | ); 15 | 16 | struct TransferStruct { 17 | address from; 18 | address receiver; 19 | uint256 amount; 20 | string message; 21 | uint256 timestamp; 22 | string keyword; 23 | } 24 | 25 | TransferStruct[] transactions; 26 | 27 | function addToBlockChain( 28 | address payable receiver, 29 | uint256 amount, 30 | string memory message, 31 | string memory keyword 32 | ) public { 33 | transactionsCount += 1; 34 | transactions.push( 35 | TransferStruct( 36 | msg.sender, 37 | receiver, 38 | amount, 39 | message, 40 | block.timestamp, 41 | keyword 42 | ) 43 | ); 44 | 45 | emit Transfer( 46 | msg.sender, 47 | receiver, 48 | amount, 49 | message, 50 | block.timestamp, 51 | keyword 52 | ); 53 | } 54 | 55 | function getAllTransactions() 56 | public 57 | view 58 | returns (TransferStruct[] memory) 59 | { 60 | return transactions; 61 | } 62 | 63 | function getTransactionCount() public view returns (uint256) { 64 | return transactionsCount; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /smart_contract/hardhat.config.js: -------------------------------------------------------------------------------- 1 | // https://eth-ropsten.alchemyapi.io/v2/1Fu4Jn3DcjegvS56l2UINAshrHVdtPJz 2 | 3 | require('@nomiclabs/hardhat-waffle'); 4 | module.exports = { 5 | solidity: '0.8.0', 6 | networks: { 7 | ropsten: { 8 | url: 'https://eth-ropsten.alchemyapi.io/v2/1Fu4Jn3DcjegvS56l2UINAshrHVdtPJz', 9 | accounts: ['c9c4b7e083ce851abaac82fb79be13b647460072bf671bc9358f316880e3e846'], 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /smart_contract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smart_contract", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "devDependencies": { 10 | "@nomiclabs/hardhat-ethers": "^2.0.3", 11 | "@nomiclabs/hardhat-waffle": "^2.0.1", 12 | "chai": "^4.3.4", 13 | "ethereum-waffle": "^3.4.0", 14 | "ethers": "^5.5.2", 15 | "hardhat": "^2.8.0" 16 | }, 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC" 20 | } 21 | -------------------------------------------------------------------------------- /smart_contract/scripts/deploy.js: -------------------------------------------------------------------------------- 1 | const main = async () => { 2 | const Transactions = await hre.ethers.getContractFactory('Transactions'); 3 | const transactions = await Transactions.deploy(); 4 | 5 | await transactions.deployed(); 6 | 7 | console.log('Transactions deployed to:', transactions.address); 8 | }; 9 | 10 | // main() 11 | // .then(() => process.exit(0)) 12 | // .catch((error) => { 13 | // console.error(error); 14 | // process.exit(1); 15 | // }); 16 | 17 | const runMain = async () => { 18 | try { 19 | await main(); 20 | process.exit(0); 21 | } catch (e) { 22 | console.error(e); 23 | process.exit(1); 24 | } 25 | }; 26 | 27 | runMain(); 28 | -------------------------------------------------------------------------------- /smart_contract/test/sample-test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require("chai"); 2 | const { ethers } = require("hardhat"); 3 | 4 | describe("Greeter", function () { 5 | it("Should return the new greeting once it's changed", async function () { 6 | const Greeter = await ethers.getContractFactory("Greeter"); 7 | const greeter = await Greeter.deploy("Hello, world!"); 8 | await greeter.deployed(); 9 | 10 | expect(await greeter.greet()).to.equal("Hello, world!"); 11 | 12 | const setGreetingTx = await greeter.setGreeting("Hola, mundo!"); 13 | 14 | // wait until the transaction is mined 15 | await setGreetingTx.wait(); 16 | 17 | expect(await greeter.greet()).to.equal("Hola, mundo!"); 18 | }); 19 | }); 20 | --------------------------------------------------------------------------------